
入力する:
W41784094 CH60104475 lasbalsrbla bla foo bar bla PT~CH60104475
W41788464 WO60444453 hellobla bla -bla foo bar 432 alaf. PT~CH60107925
W41753387 IN61026681 sim##bla-bla bla foo bar blab lba la:bla32 bla
出力:
W41784094 CH60104455 CH60104455
W41788464 WO60444453 CH60107925
W41753387 IN61026681 NA
質問:「PT~」まで3列目を切り取るには?
ただし、「PT〜」が常に存在しない場合は、「NA」が必要です。 \
タブは区切り記号です。
答え1
awk
代わりに;を使用してこれを行う方が簡単ですsed
。awk
オプションの場合:
< input awk 'BEGIN {FS=OFS="\t"} {if ($3~/PT~/) sub(/.*PT~/, "", $3); else $3="NA"; print}'
拡張:
BEGIN {
FS=OFS="\t"
}
{
if ($3 ~ /PT~/)
sub(/.*PT~/, "", $3);
else
$3 = "NA";
print
}
BEGIN {FS=OFS="\t"}
:各区切り文字列がレコードのフィールドと見なされ(1)、各レコードの後に区切り文字が印刷されるように(2)、フィールド区切り記号1と出力フィールド区切り文字2を設定します。TAB
TAB
{if ($3~/PT~/) sub(/.*PT~/, "", $3); else $3="NA"; print}
:レコードの3番目のフィールド()が正規表現$3
()と一致する場合(つまり、正規表現を含む場合)、正規表現()の最初の左端から最も広い一致()を置き換えます。部分文字列)レコード()の3番目のフィールド()に空の文字列()を追加し、そうでない場合は3番目のフィールド()を文字列()に設定してレコードを印刷します。~
PT~
/PT~/
sub()
/.*PT~/
/.*PT~/
PT~
""
$3
$3
NA
"NA"
答え2
sed -e's/\(\t.*\t\).* PT~/\1/;t' \
-e's/\t[^\t]*/\tNA/2'
これはあなたに効果があります。最後起こったPT
行の最後のフィールドにあります。
また、sed
バージョンによっては、以下を使用する必要があります。\t
脱出する。
要点は、1行に任意の数の文字で区切られた2つのタブを探し、その後にある点から文字列が来る場合を見つけることです。<space>PT~
次に、アドレス指定されたパターン空間の最初のキャプチャサブグループをs///
除くすべてのサブグループを置き換えます。公平に言えば、これは3つのフィールド制限に依存しますが、最初の置換ステートメントは次のように変更される可能性があります。\1
\(
\)
/
/
sed -e's/^\(\([^\t]*\t\)\{2\}\)[^\t]* PT~/\1/;t' ...
... GNUまたはBSDを使用して移植可能sed
...
sed -Ee's/^(([^\t]*\t){2})[^\t]* PT~/\1/;t' ...
...replaceステートメントをs///
最初の3つのフィールドにのみ明示的に制限します。
いずれの場合も、t
前の置換が成功するとest分岐が中断されるため、次のs///
置換はその行のタブで区切られた3番目のフィールドを一致しないフィールドに置き換えます。<space>PT~
文字列のみを含む文字列NA
。
sed -e's/\(\t.*\t\).* PT~/\1/;t' \
-e's/\t[^\t]*/\tNA/2' <<\IN
W41784094 CH60104475 lasbalsrbla bla foo bar bla PT~CH60104475
W41788464 WO60444453 hellobla bla -bla foo bar 432 alaf. PT~CH60107925
W41753387 IN61026681 sim##bla-bla bla foo bar blab lba la:bla32 bla
IN
W41784094 CH60104475 CH60104475
W41788464 WO60444453 CH60107925
W41753387 IN61026681 NA