
以下に示すように、国名を含む数行の情報を含むファイルがあります。
$cat country.txt
max_china_clean_foo
man_india_raw_bar
max_us_clean_bax
max_uk_raw_bar
max_canada_raw_foo
max_au_clean_bar
このファイルから国名のみを抽出したいです。現在、forループで国名を抽出している以下のコードを使用しています。
val=${val#*_}
val=${val%_clean*}
echo $val
しかし、生成された出力には国名のみが含まれているため、以下のように残りの国を抽出するために、同様のコードを少し変更して繰り返す必要がありますchina, us
。au
val=${val#*_}
val=${val%_raw*}
echo $val
clean
これは明確なコーディング方法ではないことは承知しています。そのため、または文字列が含まれるすべての行から国名を抽出するためにあなたの助けが必要ですraw
。
awk または sed を使用して、2 つの一致キーを持つすべての国名を抽出する方法はありますか? 出力は次のようになります。
china
india
us
uk
canada
au
答え1
ここでは、次の操作を実行できます。
cut -d _ -f 2 < country.txt
または、入力に_
文字のない行が含まれる場合:
awk -F _ 'NF >= 2 {print $2}' < country.txt
国名に文字が含まれている可能性があり、代わりに最初の文字と最初の文字の間またはその後の_
行の部分を返したい場合は、次のようにします。_
_raw
_clean
perl -ne 'print $1 if s/^[^_]*_(.*?)_(clean|raw)/' < country.txt
あるいはGNUの場合grep
:
grep -Po '^[^_]*_\K.*?(?=_clean|_raw)' < country.txt
を使用する場合-P
( がgrep
PCRE サポート付きでビルドされている場合)、正規表現は Perl 互換になります。これらの正規表現では、 は\K
一致した文字列の先頭をリセットし、(?=...)
は先読み演算子です...
。つまり、一致した部分にその部分が含まれずに、文字列の残りの部分が一致するかどうかを検索します。 は一致した部分を出力-o
します。そのため、ここでは と非貪欲に同等である上記にgrep
一致するものを出力します。つまり、0 個以上の文字のシーケンスで、この場合は行の先頭()にある 0 個以上のアンダースコアのシーケンスの後にアンダースコアが続き、その後に または が続くものと想定します。.*?
.*
[^_]*
^
_raw
_clean
を使用するとpcregrep
、次のように書くこともできます。
pcregrep -o1 '^[^_]*_(.*?)_(clean|raw)'
を使用すると-o1
、最初の に一致した部分が出力されます(...)
。
答え2
awkスタイルのやり方はこちら
awk -F'_' '/clean|raw/{ print $2}'