2つのテキストファイルがあります。両方ともfile1
複数file2
行があります。
$ cat file1
line one
line two
line three
line four
line five
$ cat file2
line A
line B
line C
line D
line E
line F
一つ交換したい範囲ラインfile1
(ラインから1_start
ラインへ1_end
)、ここで範囲ラインfile2
(ラインから2_start
ラインへ2_end
)。
たとえば、2,4
inの行をfromの行file1
に置き換えます。3,5
file2
これまで私ができた唯一のfile2
ことは
$ sed -n 3,5p file2
しかし、それはそれらをそこに連れて行くのに役立ちませんfile1
。可能ですかsed
?そうでない場合は、同様のツールを使用できますか?
答え1
sed
与えられた行範囲は次のように印刷できます。
sed -n 'X,Yp' filename
ここではX
、範囲の最初の行、Y
最後の行です。明示的に指示しない限り、何も印刷しないように指示し-n
ます。これは以下の範囲で行うことです。sed
p
したがって、このコマンドを簡単に3回呼び出して一時ファイルに追加し、必要な場所にファイルを移動できます。すべて結合を使用してすべて結合し、cat
すべて結合することもできます。プロセスの交換この例に示されているように(私はちょうど虚空から取得した行番号を使用しています。$
これはファイルの最後の行です):
cat <(sed -n '1,5p' file1) <(sed -n '10,12p' file2) <(sed -n '9,$p' file1) > file1.tmp && mv file1.tmp file1
file1
ここでは、6、7、8行を10、11、12行に置き換えますfile2
。
修正する:@MiniMaxさんありがとうございます指摘cat
次のようにすると、このような状況やプロセスの交換を回避できます。
{ sed -n '1,5p' file1; sed -n '10,12p' file2; sed -n '9,$p' file1; } > file1.tmp && mv file1.tmp file1
結局キスしてください。 :)
答え2
別の方法はコマンドをsed
使用することですが、内部オプションも使用する必要がある場合に便利です。r
-i
$ sed -n '3,5p; 5q;' f2 | sed -e '2r /dev/stdin' -e '2,4d' f1
line one
line C
line D
line E
line five
$ # if /dev/stdin is not supported
$ sed -n '3,5p; 5q;' f2 > t1
$ sed -e '2r t1' -e '2,4d' f1
通知をいただいたdon_crisstiに感謝します。ファイル2に必要な行があれば終了できます。
答え3
大容量入力ファイルの場合、この方法はより高速になる可能性があります。
# replacing lines m1,m2 from file1 with lines n1,n2 from file2
m1 = 2; m2 = 4; n1=3;
{ head -n $((m1-1)); { head -n $((n1-1)) >/dev/null; head -n $((n2-n1+1));
} <file2; head -n $((m2-m1+1)) >/dev/null; cat; } <file1
それここで説明されています、唯一の違いは、特定のケースの1行の範囲です。
答え4
私は最近Pythonですべての作業を始めました。したがって、必要なタスクを実行するPythonプログラムは次のようになります。
#!/usr/bin/env python2
# -*- coding: ascii -*-
"""replace_range.py"""
import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"matchfile",
help="File in which to replace lines",
)
parser.add_argument(
"matchrange",
help="Comma-separated range of Lines to match and replace",
)
parser.add_argument(
"replacementfile",
help="File from which to get replacement lines"
)
parser.add_argument(
"replacementrange",
help="Comma-separated range of lines from which to get replacement"
)
if __name__=="__main__":
# Parse the command-line arguments
args = parser.parse_args()
# Open the files
with \
open(args.matchfile, 'r') as matchfile, \
open(args.replacementfile, 'r') as replacementfile:
# Get the input from the match file as a list of strings
matchlines = matchfile.readlines()
# Get the match range (NOTE: shitf by -1 to convert to zero-indexed list)
mstart = int(args.matchrange.strip().split(',')[0]) - 1
mend = int(args.matchrange.strip().split(',')[1]) - 1
# Get the input from the replacement file as a list of strings
replacementlines = replacementfile.readlines()
# Get the replacement range (NOTE: shitf by -1 to convert to zero-indexed list)
rstart = int(args.replacementrange.strip().split(',')[0]) -1
rend = int(args.replacementrange.strip().split(',')[1]) - 1
# Replace the match text with the replacement text
outputlines = matchlines[0:mstart] + replacementlines[rstart:rend+1] + matchlines[mend+1:]
# Output the result
sys.stdout.write(''.join(outputlines))
実際の姿は次のとおりです。
user@host:~$ python replace_range.py file1 2,3 file2 2,4
line one
line B
line C
line D
line four
line five