行が多いファイルがあります。各行はパターンで始まり、gi_[0-9]
タブと単語のリストが順番に続き、すべてセミコロンで区切られます。最後の8単語だけ維持したいです(最後の部分に2単語があるので7部分)。
これは例です入力する文書:
gi_1\tDog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2\tPork;Black;White;Beige;Brown;Cyan;Purple;Red pepper
これ対応する出力しなければならない:
gi_1\tPink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2\tBlack;White;Beige;Brown;Cyan;Purple;Red pepper
ノート:タブ文字を挿入する方法が見つからなかったので、代わりに\ tを書きましたが、ファイルにタブ表示ができました。
答え1
短いsed方法:
sed 's/^\(.*\t\)[^;]*;/\1/' file
出力:
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
\(.*\t\)
- 最初の部分に必要な部分をキャプチャします。
答え2
そしてawk
:
awk -F '\t' -v OFS='\t' 'sub("^[^;]*;", "", $2)' file.txt
sub("^[^;]*;", "", $2)
;
部分文字列をタブ区切り(-F '\t'
)の2番目のフィールドで始まり、最初のフィールドに対してnullで終わる部分文字列で置き換えます。sub()
交換品があるかどうか-v OFS='\t'
出力フィールド区切り記号をタブに設定最初のフィールド(および他のすべてのフィールド)はそのまま残ります。
完全性のために、最初のフィールドのgi_
後に数字が続く必要があります。
awk -F '\t' -v OFS='\t' '$1 ~ /^gi_[[:digit:]]$/ {sub("^[^;]*;", "", $2); print}' file.txt
例:
% cat file.txt
gi_1 Dog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Pork;Black;White;Beige;Brown;Cyan;Purple;Red pepper
% awk -F '\t' -v OFS='\t' 'sub("^[^;]*;", "", $2)' file.txt
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
% awk -F '\t' -v OFS='\t' '$1 ~ /^gi_[[:digit:]]$/ {sub("^[^;]*;", "", $2); print}' file.txt
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
答え3
Perlスタイルのgrepを使用する一般的なソリューション:
$ a="gi_1 \t Dog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish"
[s@SS data]$ echo $a | grep -P -o "((^gi_. \\\t )|(?<=[; ])(?:.(?!(([; ].+)){8}))+$)" | sed ':a;N;$!ba;s/\n/ /g'
gi_1 \t Pink;Blue;Beige;Yellow;Orange;Red;Green irish
これは単語数に関係なく動作します。
非キャプチャグループと否定予測は、繰り返されるシーケンス[;に従わないすべての文字を除外します。 ]の後にランダムな文字が続きます。
始めの肯定的な予測は先行[; \ t]文字を削除します。
sed部分は真ん中の新しい行を削除します。
答え4
GNU sedを使用すると、do-untilループ構造で6つのセミコロンを見つけてこれを実行できます。
sed -e '
:loop
s/\t[^;]*;/\t/
s/;/&/6
Tloop
' yourfile