sed
ワイルドカード式を含むコマンドを使用してTSVファイルに文字を挿入したいと思います。
次のファイルがあります。
Marker Pvalue Trait Chr Pos
S3_16887238 6.172847e-09 Total_Soil_S 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Pa 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Cl 3 16887238
_All
3番目の列のすべてのテキストの末尾に次の内容を追加したいと思います。
Marker Pvalue Trait Chr Pos
S3_16887238 6.172847e-09 Total_Soil_S_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Pa_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Cl_All 3 16887238
このコマンドを使用していますが、動作しません。
sed -i 's/Total_Soil_\(.*\)/&_\1_All/g' top1.txt
S
これはサンプルファイルなので、およびをPa
置き換えることができますCl
。
答え1
sed
変更したいデータから正確な場所を見つけるのは難しいので、表形式のデータを使用しないことをお勧めします。このsed
ユーティリティは、テキストなどの非構造化データを処理するのに適しています。
使用ミラー(mlr
;構造化データ操作用に特別に設計されたツール)は、_All
各TSVレコードフィールドのデータの末尾に文字列を追加します。Trait
$ mlr --tsv put '$Trait .= "_All"' file
Marker Pvalue Trait Chr Pos
S3_16887238 6.172847e-09 Total_Soil_S_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Pa_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Cl_All 3 16887238
mlr
オプションと組み合わせて-I
変更を適用します。
Total_Soil
フィールドが文字列で始まる場合にのみ変更するようにしてから、次を使用する必要がありますか?
mlr --tsv put '$Trait =~ "^Total_Soil" { $Trait .= "_All" }' file
以下を使用して、各レコードのタブで区切られた3番目のフィールドのデータの末尾にawk
文字列を追加します。_All
$ awk -F '\t' 'BEGIN { OFS=FS } NR > 1 { $3 = $3 "_All" }; 1' file
Marker Pvalue Trait Chr Pos
S3_16887238 6.172847e-09 Total_Soil_S_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Pa_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Cl_All 3 16887238
1
コードの末尾を後続すると、変更されawk
たレコードが無条件に出力されます。どうやって見ると書くの短縮形だ{ print }
。ヘッダーの変更を明示的に防ぐ必要があることに注意してください。NR > 1
テストが次のように評価されると、フィールドの使用と修正のみがテストされます。本物(NR
現在のレコードのシリアル番号です。)
出力を新しいファイルにリダイレクトし、新しいファイルの名前を元の名前に変更します。またはGNUを使用している場合は、指示に従い、以下を使用してくださいawk
。-i inplace
もう一つの質問+答えです。
同様に、文字列で始まる3番目のフィールドのみを変更するには、Total_Soil
次のようにします。
awk -F '\t' 'BEGIN { OFS=FS } NR > 1 && $3 ~ /^Total_Soil/ { $3 = $3 "_All" }; 1' file
Perl の使用は次のようにほぼ同じですawk
。
$ perl -F'\t' -e 'BEGIN { $" = "\t" } if ($. > 1) { $F[2] .= "_All" } print "@F"' file
Marker Pvalue Trait Chr Pos
S3_16887238 6.172847e-09 Total_Soil_S_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Pa_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Cl_All 3 16887238
Total_Soil
データのみを変更してください。
perl -F'\t' -e 'BEGIN { $" = "\t" } if ($. > 1 && $F[2] =~ /^Total_Soil/) { $F[2] .= "_All" } print "@F"' file
答え2
使用幸せ(以前のPerl_6)
~$ raku -ne 'BEGIN put get; my @a = .split("\t"); @a.[2] = @a.[2] ~ "_All"; put @a.join("\t");' file
RakuはPerlプログラミング言語ファミリーのメンバーです。 Rakuの利点の1つは、外部ライブラリ(または特別なフラグ)を必要としない組み込みUnicodeの高度なサポートです。
上記は@Kusalanandaの優れたPerl(5)答えをかなり直接翻訳したものです。-ne
Rakuの非自動印刷「1行ずつ」コマンドラインフラグを使用してください。ヘッダー行をそのまま印刷するには、BEGIN
ページャを使用してput get
最初の行に挿入します(印刷にはターミネータを使用します)get
。
line-by-line コマンドの本文は次のように動作します。配列を宣言し、タブの入力行をmy @a
その配列に割り当てます。$_
.split("\t")
.split("\t")
$_.split("\t")
3番目の要素(列など)を取得し、チルダ付きの末尾の文字列に関連付けられている@a.[2]
同じ要素で上書きします。@a.[2] ~ "_All"
_All
その後、すべての@a
要素を取り込み、join
タブで再グループ化して出力しますput
。
入力例:
Marker Pvalue Trait Chr Pos
S3_16887238 6.172847e-09 Total_Soil_S 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Pa 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Cl 3 16887238
出力例:
Marker Pvalue Trait Chr Pos
S3_16887238 6.172847e-09 Total_Soil_S_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Pa_All 3 16887238
S3_16887238 6.172847e-09 Total_Soil_Cl_All 3 16887238
答え3
sedを使用すると、次のことができます。
sed 's/Total_Soil_[^[:blank:]]*/&_All/' top1.txt
これをインラインで実行するには、-i
sedの後に追加してください。
編集する:以下を除くすべての項目と一致する[^ ]
には、次のように置き換えます。[^[:blank:]]
スペースそしてタブ。