約8,000のレコードを含む区切りファイルがあります|
。
3列が空の場合は2列の値に変更したいと思います。私たちはこれをどのように達成しますか?
入力する:
1|100437251|
2|51414204|
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
出力:
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
sed
交換コマンドを試してみましたsed -i "s/ /$2/g" input > output
。
答え1
そしてsed:
sed -E 's/^([^|]*\|)([^|]*)\|$/\1\2|\2/' infile
この部分は、([^|]*\|)
最初の列と区切り文字(\1
逆参照)をキャプチャします。
この部分は([^|]*)
2番目の列(\2
逆参照)をキャプチャします。
この部分は\|$
行末の最後の区切り文字をキャプチャし、その後に他の区切り文字はありません(3番目の列が空であることを意味します)。
このセクションでは、\1\2|\2
逆参照アドレスを使用して最初と2番目の列を返し、区切り文字を使用して2番目の列を再コピーします。
3番目の列が空ではなく、タブ/スペース([[:space:]]
)などの空白文字が含まれる可能性がある場合は、代わりにこの列を使用してください。
sed -E 's/^([^|]*\|)([^|]*)\|[[:space:]]*$/\1\2|\2/' infile
そしてアッ:
awk 'BEGIN{ FS=OFS="|" } $3 ~/^[[:space:]]*$/ { $3=$2 }1' infile
FSはF生産するS区切り記号、OFSの例酸素出力F生産するS次に、3番目の列が空であるか/タブ/スペースであることを確認し、その内容を2番目の列と同じように更新します。次に印刷します1
。
答え2
を使用しawk
、3番目のフィールドにスペース以外の文字が含まれていない限り、3番目のフィールドを2番目のフィールドに置き換えます。
$ awk -F '|' 'BEGIN { OFS = FS } $3 !~ /[^[:blank:]]/ { $3 = $2 }; 1' file
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
sed
3番目のフィールドが空白または空白のみを含む場合は、2番目のフィールドの番号を挿入するために使用されます。
$ sed 's/\([[:digit:]]\{1,\}\)|[[:blank:]]*$/\1|\1/' file
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
3番目のフィールドは次のとおりです。いつも2番目のフィールドと同様に、3番目のフィールドのすべてのテストを無視し、2番目のフィールドの値になるように強制することもできます。
まず、次を使用しますawk
。
$ awk -F '|' 'BEGIN { OFS = FS } { $3 = $2 }; 1' file
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
でも
$ awk -F '|' 'BEGIN { OFS = FS } { print NR, $2, $2 }' file
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
これにより、最初の列も再生成されます。
次に、次を使用しますsed
。
$ sed 's/|[^|]*$//; s/[[:digit:]]\{1,\}$/&|&/' file
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
このsed
コマンドは最初に最後のフィールドを削除してから、削除されたフィールドより前のフィールドから再生成します。
または、次のようなもの
$ cut -d '|' -f 2 file | sed '=; s/.*/&|&/' | sed 'N; y/\n/|/'
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
2番目のフィールドを使用してデータを抽出し、列挙に使用してフィールドの重複をcut
関連付け=
て作成sed
し、最後に正しい区切り文字を使用してデータに行番号を追加します。
(プロセスの代替を使用)の組み合わせを使用して、シェルでcut
これを行うこともできます。paste
bash
$ paste -d '|' <( cut -d '|' -f 1,2 file ) <( cut -d '|' -f 2 file )
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
答え3
そしてawk
:
awk -F'|' -v OFS='|' '{if($3=="")$3=$2}1'
sed
2番目の列が常に数値の場合の簡単な例です。
sed -E "s/([0-9]*)\|$/\1|\1/"
答え4
、を使って空であるかどうかをawk
確認してください$3
。
awk -F'|' -v OFS='|' '$3 == "" {$3=$2} 1' file
1|100437251|100437251
2|51414204|51414204
3|111651604|111651604
4|8321737|8321737
5|27263401|27263401
- または
awk -F'|' -v OFS='|' 'length($3) == 0 {$3=$2} 1' file