下線(_)で区切られた複数の列を持つファイルがあります。
ほとんどの列は最初の文字が大文字で始まり、一部の列が小文字で始まります。
大文字で始まり、次の列は、小文字で始まる各行の文字列を抽出する予定です。これはすべての行で少なくとも1回発生します。(アップデート:最初のゲームしかなかったらよかったでしょう)。トリッキーな部分は、これがすべての行の同じ列で発生するわけではありません。
たとえば、
Today_is_a_Good_Day
It_Doesnt_rain
i_dont_Like_rainy_day
希望の出力:
Today_is
Doesnt_rain
Like_rainy
grep / sed / awkまたは他のコマンドを使用してこのタイプのテキスト抽出を実行する方法はありますか?
私の問題に対する同様の解決策を見つけようとしましたが、見つかりませんでした。
アップデート:少なくともあるでしょう
答え1
grep
PCREおよび以下でサポートされている実装-o
:
$ grep -P -o '(?<![^_])\p{Lu}[^_]*_\p{Ll}[^_]*' < your-file
Today_is
Doesnt_rain
Like_rainy
(サポートしていない場合は置き換えることができますgrep -P
。)pcregrep
grep
-P
u
これは、大文字、L
後にゼロ個以上のnn-s、小文字、および別のゼロ個以上のnon-sが続く順序であり、全体は後ろにnon-がない場合にのみ一致します(たとえば、後ろまたは行の先頭)。_
_
l
L
_
_
_
これにより、一致する項目がそれぞれ1行に印刷されます。各行の最初の一致に制限するには、別の方法で実行できます。
grep -P -o '^(.*?_)??\K\p{Lu}[^_]*_\p{Ll}[^_]*' < your-file
各行の最後の一致は同じですが、前半を占める部分に貪欲なバージョンの演算子を使用します。
grep -P -o '^(.*_)?\K\p{Lu}[^_]*_\p{Ll}[^_]*' < your-file
答え2
$ grep -o '[[:upper:]][[:alpha:]]*_[[:lower:]][[:alpha:]]*' file
Today_is
Doesnt_rain
Like_rainy
これは大文字で始まり、その後に任意の数のアルファベット文字、アンダースコア、小文字、および(おそらく)より多くのアルファベット文字が続く文字列を抽出します。
ただし、一致が複数ある場合、上記のコードは行ごとに複数の一致を抽出します。
次のsed
コマンドにはこの問題はありません。最後各行には次の文字列があります。)
$ sed -n 's/.*\([[:upper:]][[:alpha:]]*_[[:lower:]][[:alpha:]]*\).*/\1/p' file
Today_is
Doesnt_rain
Like_rainy
答え3
awkメソッド
awk -F'_' -v OFS='_' '{
for (i=1; i<NF; i++) {
if ($i ~ /^[[:upper:]]/ && $(i+1) ~ /^[[:lower:]]/) {
print $i, $(i+1)
break
}
}
}' file
break
最初の一致のみが印刷されていることを確認してください。
答え4
sed 's/.*\([A-Z][^_]*_[a-z][^_]*\).*/\1/' <your-file
編集:Greedy sedは最後の一致を提供します。最初に一致するawkソリューション:
awk '{match($0,/([A-Z][^_]*_[a-z][^_]*)/,a); print a[1]}' <your-file