部分文字列を見つけて、テキストファイルから次の行を抽出します。

部分文字列を見つけて、テキストファイルから次の行を抽出します。

次の形式のタブで区切られたテキストファイルがあります。

Name      city            info
Stef     NY=123         ID=1;CITY=NY
John    SE=981;819      ID=110;CITY=SE
Stef      SE=01         ID=20;CITY=SE
Kelly   SE=111;787      ID=100;CITY=NY
Lena    NY=815;981;1    ID=2111;CITY=NY

3番目の列では、IDが100を超える新しいテキストファイルに行を抽出しようとしているため、予想される出力は次のとおりです。

Name      city            info
John    SE=981;819     ID=110;CITY=SE
Lena    NY=815;981,1   ID=2111;CITY=NY

これまで持っているawkコマンドは次のとおりです。


awk '$3 !~ /^ID=[0-9];/' file.txt > output.txt

ただし、これによりIDが9以下の行のみが削除されます。 IDが100未満のすべての行を除外する方法がわかりません。どうすればこれを達成できますか?洞察力を高く評価いたします。

答え1

使用ミラー

$ mlr --tsv filter 'i = splitkv($info, "=", ";"); i["ID"] > 100' file.txt
Name    city    info
John    SE      ID=110;CITY=SE
Lena    NY      ID=2111;CITY=NY

GNU awkを使う:

$ gawk -F '\t' 'NR==1 || match($3,/ID=([0-9]+)/,arr) && arr[1]+0 > 100' file.txt
Name    city    info
John    SE      ID=110;CITY=SE
Lena    NY      ID=2111;CITY=NY

答え2

実際の入力が提供した例と同じであるとします。

$ awk -F'[=;]' 'NR==1 || $(NF-2)>100' file
Name      city            info
John    SE=981;819      ID=110;CITY=SE
Lena    NY=815;981;1    ID=2111;CITY=NY

[=;]各レコードをフィールドに分割するように awk に指示するように FS を設定する方法は次のとおりです。

$ awk -F'[=;]' '{print "---------" ORS $0; for (i=1;i<=NF;i++) print NF, i, "<"$i ">"}' file
---------
Name    city    info
1 1 <Name       city    info>
---------
Stef    NY=123  ID=1;CITY=NY
5 1 <Stef       NY>
5 2 <123        ID>
5 3 <1>
5 4 <CITY>
5 5 <NY>
---------
John    SE=981;819      ID=110;CITY=SE
6 1 <John       SE>
6 2 <981>
6 3 <819        ID>
6 4 <110>
6 5 <CITY>
6 6 <SE>
---------
Stef    SE=01   ID=20;CITY=SE
5 1 <Stef       SE>
5 2 <01 ID>
5 3 <20>
5 4 <CITY>
5 5 <SE>
---------
Kelly   SE=111;787      ID=100;CITY=NY
6 1 <Kelly      SE>
6 2 <111>
6 3 <787        ID>
6 4 <100>
6 5 <CITY>
6 6 <NY>
---------
Lena    NY=815;981;1    ID=2111;CITY=NY
7 1 <Lena       NY>
7 2 <815>
7 3 <981>
7 4 <1  ID>
7 5 <2111>
7 6 <CITY>
7 7 <NY>

答え3

ヘッダーの下のファイル全体の形式が同じ場合:

awk -F '=|;' 'NR==1; $2>100' location

区切り文字をまたはに設定し、=ヘッダー;を印刷してから、2番目のフィールドが100より大きい最初の行の後のすべての行を印刷します。

出力:

Name      city      info
John       SE     ID=110;CITY=SE
Lena       NY     ID=2111;CITY=NY

答え4

非常に無邪気な解決策は次のとおりです。

awk -F'\t' '{
    o=$3
    sub(/ID=/,"",o)
    if(o + 0 > 100) print
}' test 

より進化したアプローチは次のとおりです。

awk -F'\t' 'NR == 1 || (match($3, /[0-9]+/) && substr($3, RSTART, RLENGTH) + 0 > 100)' test

match3番目のフィールドには少なくとも3桁の数字を入力してみてください。

match変数は、正規表現が一致を開始するインデックスに設定されるか、一致がRLENGTHまったく見つからない場合はゼロに設定されます。

その後、完全一致(RSTARTRLENGTH)が100より大きいことを確認できます。その場合は、行全体を印刷します。

関連情報