「sed」を使用してTSVファイルのフィールドの末尾にテキストを挿入する

「sed」を使用してTSVファイルのフィールドの末尾にテキストを挿入する

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

_All3番目の列のすべてのテキストの末尾に次の内容を追加したいと思います。

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)答えをかなり直接翻訳したものです。-neRakuの非自動印刷「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

https://docs.raku.org
https://raku.org

答え3

sedを使用すると、次のことができます。

sed 's/Total_Soil_[^[:blank:]]*/&_All/' top1.txt

これをインラインで実行するには、-isedの後に追加してください。

編集する:以下を除くすべての項目と一致する[^ ]には、次のように置き換えます。[^[:blank:]]スペースそしてタブ

関連情報