awkで部分文字列(または切り取り、sedなど)をしたい文字列があります。
しかし、フィールド区切り文字を維持したいと思います。
ファイルには、フィールド区切り文字の後にランダムな文字数を含む完全にランダムな量のゴミがあります。
例えば
dog.pgp.123sdadog.pgpsjaksdasdasdawdog.pgp -
asasdawad2
3つの出力がすべて次のようになります。
犬.pgp
明らかに、ここの公開フィールドは「.pgp」ですが、標準awkは常にフィールド区切り文字を削除します。
'{sub(/.pgp.*/,""); print}'
または
awk -F".PGP." '{print $1}'
分離膜を維持する方法はありますか?
答え1
for string in Dogs.pgp.123sda Dogs.pgpsjaksdasdasdaw Dogs.pgp-asasdawad2
do
printf '%s --> %s\n' "$string" "${string%${string#*.???}}"
done
出力:
Dogs.pgp.123sda --> Dogs.pgp
Dogs.pgpsjaksdasdasdaw --> Dogs.pgp
Dogs.pgp-asasdawad2 --> Dogs.pgp
このループは3つの文字列を繰り返します。ループ本体には、元の文字列が変換された文字列と一緒に印刷されます。
最初の点の前の文字列部分と点の後の3文字を除くすべての部分を削除して文字列を変換します。
これは、最初に元の文字列から削除する項目を特定することによって行われます。これは${string#*.???}
、最初の点と3つの文字をさらに削除した後の残りの文字列です。次に、文字列の末尾からその値を削除します${string%${string#*.???}}
。
ループが繰り返される場合ファイル名たとえば、と一致する*.pgp*
と、ファイル名に改行文字が含まれている場合も処理できます。上記の変換を混乱させる唯一のことは、部分.pgp
文字列の前にドットがある場合ですが、.pgp
代わりに明示的に一致させることでこれを行うことができます.???
。
for fname in *.pgp*
do
printf '%s --> %s\n' "$fname" "${fname%${fname#*.pgp}}"
done
答え2
どうですか?
awk -F '.pgp' '{print $1 FS}'
代わりにawkを使いたいですperl -pe 's/\.pgp\K.*//'
。
答え3
一致と部分文字列を使用して問題を解決したと思います。
'match($0, /REGEX/) {sub(/REGEX/, substr($0, RSTART, RLENGTH) ); print}'
答え4
awk substrメソッドを試してみました。
awk '{print substr($1,1,8)}' filename
出力は次のとおりです
Dogs.pgp
Dogs.pgp
Dogs.pgp