Let M=3
and 。ライン入力をライン入力に変更しN=4
たいです。以下を使用して文字列を置き換えることができます。M
file1
N
file2
sed
sed -i '3s/.*/stringToReplace/' file1
私はこれを使ってawk
行を得ることができますN
file2
awk 'NR==4' "file2"
これら2つをどのように組み合わせることができますか?試してみると
sed -i '3s/.*/{awk 'NR==4' "file2"}/' file1
次に、M
lineを文字通りの意味に置き換えます{awk 'NR==4' "file2"}
。
答え1
任意の入力を処理するためにこれを正しく実行する方法はいくつかあります。
GNUsed
と以下をサポートするシステムを使用してください/dev/stdin
。
sed -n "${n}{p;q;}" file2 | sed -e "$m{r/dev/stdin" -e 'd;p;}' file1
または少し短い1:
sed $n'!d;q' file2 | sed -e $m'{r /dev/stdin' -e 'd;p;}' file1
sed
プロセスの交換をサポートするシェルを使用してください。
sed '1h;1d;'$((m+1))'x' <(sed ${n}'!d;q' file2) file1
次のように書くこともできます。
sed ${n}'!d;q' file2 | sed '1h;1d;'$((m+1))'x' - file1
デフォルトでは、1回のsed
呼び出しは行を抽出し、別の呼び出しn
からfile2
最初のオペランドに読み込みますsed
。これを保持バッファに保存して削除し、2番目のオペランドの内容を読み込みます。つまりfile1
、交換時にラインでバッファm+1
(入力結合))。
sed
以下を介してスクリプトファイルの読み取りをサポートしている人:-f
stdin
sed ${n}'!d;i\
'${m}'c\\
s/\\/&&/g
q' file2 | sed -f - file1
ここで最初のsed
ものは、行を次のスクリプトファイルn
に置き換えます。file2
${m}c\
line_n_content_here_with_any_backslash_escaped
次に、2番目の項目のsed
処理に使用されますfile1
(例:その行をm
次のテキストに置き換えます。)。 anyを使用しa\
たりテキストを追加したりするときなど、元のテキスト内のすべてのバックスラッシュ(含まれている改行も含みますが、ここには1つのみ)をエスケープする必要がありますi\
。c\
<backslash> characters in text shall be removed, and the following character shall be treated literally.
いずれにせよ、sed
常に人気のあるs
代替コマンドを使用できます。sed
挿入された代替文字列がすべての予約文字をエスケープしていることを確認してください。- この特別な場合には1行です。
line=$(sed ${m}'!d;s|[\/&]|\\&|g;q' file2)
次に、次のものを交換します。
sed ${m}'s/.*/'"$line"'/' file1
大規模な入力ファイルの場合は、以下を実行できます。
{ head -n $((m-1)); { head -n $((n-1)) >/dev/null; head -n 1; } <file2; head -n 1 >/dev/null; cat; } <file1
これは次のことを行います。
print (m-1) lines from file1
discard (n-1) lines from file2
print n-th line from file2
discard m-th line from file1
print the remaining lines from file1
何人かのhead
人々は愚かで何をすべきかわからないが標準準拠したがって、これがすべての設定で機能するわけではありませんが、それが機能している場合はsed
速度の面で優れています。awk
1:一部のシェルでは、これが機能するために履歴拡張を無効にする必要があるかもしれません!
...
また、正の整数でなければならないので、ここで引用する必要はありません$n
。$m
答え2
この試み:
$ cat f1
foo
bar
xyz
baz
temp
good
$ cat f2
1
2
3
4
5
6
$ awk -v m=3 -v n=4 'NR==FNR{if(FNR==n) s=$0; next} FNR==m{$0=s} 1' f2 f1
foo
bar
4
baz
temp
good
NR==FNR
最初のファイルが処理されている場合にのみ真if(FNR==n) s=$0
n番目の行を減らすと変数に保存next
これにより、最初のファイルの処理中に残りのコードは実行されません。FNR==m{$0=s}
2番目のファイルパラメータのm行目の場合は置き換えます。1
修正を含む入力履歴を印刷します。- ファイル入力パラメータの順序に注意してください。
if(FNR==n){s=$0;nextfile}
n行目以降のライン処理を避けるために使用できます。
~からGNU awk マニュアル-ありがとう@iruvar
注:nextfileは長年にわたって一般的な拡張機能でした。 2012年9月にPOSIX規格に統合されました。オースティングループのウェブサイトをご覧ください。
答え3
短いsed方法:
サンプルファイルf1
:
f1 line1
f1 line2
f1 line3
f1 line4
f1 line5
サンプルファイルf2
:
ID1,value12,value13
ID1,value22,value23
ID1,value32,value33
ID2,/value42/,~value43~
ID3,value52,value53
働く:
sed '3 s/.*/'"$(sed -n '4{ s/\//\\\//g;p;}' f2)"'/;' f1
出力:
f1 line1
f1 line2
ID2,/value42/,~value43~
f1 line4
f1 line5
答え4
awkとsedを混ぜないでください。完全なawkソリューションが利用可能
ファイル1:
file1 1
file1 2
file1 3
file1 4
ファイル2:
file2 1
file2 2
file2 3
file2 4
awk -v m=3 -v n=4 'NR == FNR { filea[FNR]=$0 } FNR != NR { fileb[FNR]=$0 } END { for (i=1;i<=FNR;i++) { if ( i == m ) { print fileb[n] } else { print filea[i] } } } ' file1 file2
分割:
NR == FNR {
filea[FNR]=$0
}
FNR != NR {
fileb[FNR]=$0
}
END {
for (i=1;i<=FNR;i++) {
if ( i == m ) {
print fileb[n]
}
else {
print filea[i]
}
}
}
NRとFNRを比較して、file1とfile2のレコードを決定します(NR = FNRの場合は最初のファイルにあることがわかります)。 file1のレコードとしてfilea配列を設定し、file2のレコードとしてfileb配列を設定しました。次に、filea配列のすべてのレコードを繰り返し、渡されたパラメータmが3以外の場合にのみ内容を印刷します。そうであれば、渡されたパラメータnによって決定された配列ファイルの添え字を印刷します。