条件付きで file1 の行を file2 の対応する行に置き換えます。

条件付きで file1 の行を file2 の対応する行に置き換えます。

たとえば、次の2つのファイルがあります。

ファイル1:

1
4
X
5
X
7

ファイル2:

2
3
5
X
X
1

Xfile1の-linesをfile2の対応する行の内容に置き換えたいと思います。

結果:

1
4
5
5
X
7

私は同じCLIコマンドを使用するソリューションを好みますsed

答え1

file2 がメモリに収まる場合、awk を使用できます。まず、file2 を読み込み、次に file1 の処理中に「X」が表示された場合は、file2 配列でそのファイルを置き換えます。

$ awk 'NR == FNR { lines[NR]=$0; } NR != FNR { if ($0 == "X") print lines[FNR]; else print $0 }' file2 file1

再フォーマットすると、次のようになります。

$ awk 'NR == FNR { lines[NR]=$0; } 
       NR != FNR { if ($0 == "X") print lines[FNR]; 
                   else           print $0 
                 }' file2 file1

file2 は最初のファイル名、file1 は 2 番目のファイル名です。

答え2

$ paste file1 file2 | awk -F '\t' '$1 == "X" { $1 = $2 } { print $1 }'
1
4
5
5
X
7

このpasteコマンドはタブ区切りの出力を生成します。

1       2
4       3
X       5
5       X
X       X
7       1

最初のフィールドが文字の場合、awkスクリプトはタブで区切られた最初のフィールドを2番目のフィールドの内容に設定し、最初のX(現在変更されている可能性がある)フィールドを印刷します。

さまざまな方法グレンジャックマンがおすすめする作品渡されたデータを変更せずに、最初の列のデータに基づいて印刷するフィールドを選択します。

$ paste file1 file2 | awk -F '\t' '{ print $1 == "X" ? $2 : $1 }'

GNUの使用sed:

$ paste file1 file2 | sed -E -e '/^X/s/^[^\t]+\t//' -e 's/\t.*$//'
1
4
5
5
X
7

これら2つのsed式は、次のことを行います。

  1. 現在行がで始まる場合、X最初の置換は最初のタブを含むすべての項目を削除します。pasteこれにより、最初の列がある場合、出力の2番目の列が最初の列に効果的に移動されますX
  2. 2番目の式は、タブ文字とそれに続くすべての項目を削除します。これにより、興味のないデータが削除されます。

答え3

バッシュと

while IFS= read -r -u3 f1; IFS= read -r -u4 f2; do
    [[ $f1 == X ]] && echo "$f2" || echo "$f1"
done 3<file1 4<file2

またはより一般的にはPOSIX

while IFS= read -r f1 <&3; IFS= read -f f2 <&4; do
    [ "$f1" = X ] && echo "$f2" || echo "$f1"
done 3<file1 4<file2

関連情報