以下に示すように、国名に関する情報を含む複数行のファイルがあります。
$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
(PCREサポートで構築されている場合grep
)正規表現はPerl互換正規表現です。これらの正規表現では、\K
一致する文字列の先頭がリセットされ、プレビュー(?=...)
演算子です。つまり、...
一致する部分に含まれる残りの文字列で一致するものを探します。出力を一致する部分にします-o
。したがって、ここでは上記と一致するものを印刷します。つまり、貪欲ではない同等物です。つまり、できるだけ短いゼロ個以上の文字シーケンス(この場合、ゼロ個以上の下線シーケンスの後に続く)です。 ()は()行を開始し、その後ろにアンダースコアが続き、後ろに続くか続くと見なされます。grep
.*?
.*
[^_]*
^
_raw
_clean
これを使用して、pcregrep
次のように書くこともできます。
pcregrep -o1 '^[^_]*_(.*?)_(clean|raw)'
それを使用すると、-o1
最初の部分と一致する部分が印刷されます(...)
。