GNU/Linux >> Linux の 問題 >  >> Linux

行番号によって、あるファイルの行を別のファイルの行に置き換えます

awk の使用 :

awk -v a='2,4,5,7' -v b='1,2,5,8' '
BEGIN { split(a, ax, ","); split(b, bx, ",");
        for(n in ax) mapping[ bx[n] ] =ax[n];
};
NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };
{ print (FNR in hold)? hold[FNR]: $0; }' fileB fileA

ここでは、行番号を awk として渡します -v a='...' でアリブル (fileA の場合) および b='...' (fileB の場合)、split() それらを区切り記号としてコンマ文字の配列に入れます (a に注意してください)。 と b 以前は変数でしたが、現在は ax です および bx は配列です)。

次に、別の mapping を作成します ax からの配列 と bx fileA の行を fileB の行に置き換える配列;

mapping のキー (またはインデックス) 次のように、配列はファイル B の行番号であり、これらのキーの値はファイル A の行番号です。

mapping 配列は:

Key    Value
1      2
2      4
5      5
8      7

つまり、上記のキー (1 の FNR) と一致する fileB から行番号を読み取るだけです。 、 258 )、したがって、次のようにします:

NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };

さて、mapping[FNR] の値は? ? mapping をチェックすると 上記の配列は、次のようになります:

mapping[1] --> 2; then-we-have    hold[ mapping[1] ] --> hold[2]=$0
mapping[2] --> 4; then-we-have    hold[ mapping[2] ] --> hold[4]=$0
mapping[5] --> 5; then-we-have    hold[ mapping[5] ] --> hold[5]=$0
mapping[8] --> 7; then-we-have    hold[ mapping[8] ] --> hold[7]=$0

mapping の値を使用しました hold のキーとしての配列 配列と hold 配列に含まれるようになりました:

Key     Value
2       Argentina
4       Switzerland
5       Denmark
7       Colombia

最後のステップは hold でキーを使用することです fileA 内の一致する行番号として配列し、その行を hold からのそのキーの値に置き換えます その行番号が配列内に見つかった場合は配列、見つからない場合は行自体を出力します (三項演算子:condition? if-true : if-false )、そしてそれを次のように行います:

{ print (FNR in hold)? hold[FNR]: $0; }

標準の sed を使用する :

$ printf '%ds/^/%dc\\\\\\\n/p\n' 1 2 2 4 5 5 8 7 | sed -n -f /dev/stdin fileB | sed -f /dev/stdin fileA
Italy
Argentina
USA
Switzerland
Denmark
Japan
Colombia

コマンド パイプライン

printf '%ds/^/%dc\\\\\\\n/p\n' 1 2 2 4 5 5 8 7 |
sed -n -f /dev/stdin fileB |
sed -f /dev/stdin fileA

最初に sed を生成します printf を使用して、行番号の各ペアの代替ステートメント . printf の出力 呼び出しは次の sed です スクリプト:

1s/^/2c\\\
/p
2s/^/4c\\\
/p
5s/^/5c\\\
/p
8s/^/7c\\\
/p

この sed スクリプトは 1 行目、2 行目、5 行目、8 行目に作用し、nc\ を挿入します。 その後にリテラル改行が続きます (行番号 n の場合) ) 影響を受ける行の先頭。

これを fileB 全体で実行する (sed -n を使用) ) 新しい sed を生成します スクリプト:

2c\
Argentina
4c\
Switzerland
5c\
Denmark
7c\
Colombia

c コマンドは、行を \ に続くテキストに置き換えます であるため、スクリプトは行 2、4、5、および 7 を置き​​換えます。

これを fileA に適用 結果を生成します。

最初の列に fileB の行番号が含まれているファイルから行番号を読み取る 、2 列目には fileA の行番号が含まれます :

$ cat number-pairs
1 2
2 4
5 5
8 7
$ awk '{ printf "%ds/^/%dc\\\\\\\n/p\n", $1, $2 }' number-pairs | sed -n -f /dev/stdin fileB | sed -f /dev/stdin fileA
Italy
Argentina
USA
Switzerland
Denmark
Japan
Colombia

明らかに $1 を交換できます と $2 awk で 列を逆の順序で格納したい場合は式を使用してください。


Linux
  1. 大きなファイルにSedとParallelを使用して、行を別のコンテンツに置き換えますか?

  2. 行の範囲を行の範囲(sedまたはその他)に置き換えますか?

  3. パターンに一致する行を別のファイルの行に順番に置き換えますか?

  1. 改行をNulに置き換えますか?

  2. Linuxコマンドラインでファイルから特定の行を削除する

  3. Linuxでjar内のファイルをコマンドラインに置き換える方法は?

  1. ファイル内の文字列を置き換える方法は?

  2. 別のファイルにない1つのファイルの行を取得するためのツール?

  3. 複数行の Sed 置換