ファイル内の行全体を bash スクリプトで置き換えたい状況があります。行番号は常に同じであるため、ハードコーディングされた変数にすることができます。
その行の一部の文字列を置き換えようとしているのではなく、その行を完全に新しい行に置き換えたいだけです。
これを行うための bash メソッド (または .sh スクリプトにスローできる単純なもの) はありますか。
最大ではありませんが、これはうまくいくはずです:
sed -i 'Ns/.*/replacement-line/' file.txt
どこN
をターゲット行番号に置き換える必要があります。これにより、元のファイルの行が置き換えられます。変更したテキストを別のファイルに保存するには、-i
オプションをドロップします。
sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
私は実際にこのスクリプトを使用して、しばらく前に当社の UNIX サーバーの cron ファイルのコード行を置き換えました。通常のシェル スクリプトとして実行しましたが、問題はありませんでした。
#Create temporary file with new line in place
cat /dir/file | sed -e "s/the_original_line/the_new_line/" > /dir/temp_file
#Copy the new file over the original file
mv /dir/temp_file /dir/file
これは行番号ではありませんが、 の前に行番号s/
を置き、 の代わりにワイルドカードを配置することで、簡単に行番号ベースのシステムに切り替えることができますthe_original_line
。
行 4 をテキスト "different" に置き換えたいとします。次のように AWK を使用できます。
awk '{ if (NR == 4) print "different"; else print $0}' input_file.txt > output_file.txt
AWK は、入力を「フィールド」に分割された「レコード」と見なします。デフォルトでは、1 行が 1 レコードです。 NR
表示されたレコードの数です。 $0
現在の完全なレコードを表します (while$1
はレコードの最初のフィールドなどです。デフォルトでは、フィールドは行の単語です)。
したがって、現在の行番号が 4 の場合、文字列 "different" を出力しますが、それ以外の場合は行を変更せずに出力します。
AWK では、 で囲まれたプログラム コードは、{ }
入力レコードごとに 1 回実行されます。
AWK プログラムを単一引用符で囲んで、シェルが$0
.
編集: 以下のコメントで @chepner からのより短くよりエレガントな AWK プログラム:
awk 'NR==4 {$0="different"} { print }' input_file.txt
レコード (行) 番号 4 のみ、レコード全体を文字列 "different" に置き換えます。次に、入力レコードごとにレコードを出力します。
明らかに、私の AWK スキルは錆びています。ありがとう、@chepner。
編集: @Dennis Williamson のさらに短いバージョンも参照してください:
awk 'NR==4 {$0="different"} 1' input_file.txt
これがどのように機能するかはコメントで説明されています: は1
常に true と評価されるため、関連するコード ブロックは常に実行されます。ただし、関連付けられたコード ブロックはありません。つまり、AWK は行全体を出力するというデフォルトのアクションを実行します。AWK は、このような簡潔なプログラムを許可するように設計されています。
このテスト ファイル (test.txt) を考えると
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
Duis eu diam non tortor laoreet
bibendum vitae et tellus.
次のコマンドは、最初の行を「改行テキスト」に置き換えます
$ sed '1 c\
> newline text' test.txt
結果:
newline text
consectetur adipiscing elit.
Duis eu diam non tortor laoreet
bibendum vitae et tellus.
詳細はこちら
http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/
bashでは、N、Mを行番号に、xxx yyyを必要なものに置き換えます
i=1
while read line;do
if((i==N));then
echo 'xxx'
elif((i==M));then
echo 'yyy'
else
echo "$line"
fi
((i++))
done < orig-file > new-file
編集
実際、このソリューションには、文字「\0」「\t」および「\」にいくつかの問題があります。
"\t"、読み取りの前に IFS= を置くことで解決できます: "\"、行末に -r を指定
IFS= read -r line
ただし、「\0」の場合、変数は切り捨てられます。純粋なbashには解決策がありません: Bashの変数にヌル文字(\0)を含む文字列を割り当てます しかし、通常のテキストファイルにはヌル文字\0はありません
perl がより良い選択でしょう
perl -ne 'if($.==N){print"xxx\n"}elsif($.==M){print"yyy\n"}else{print}' < orig-file > new-file
Chepnerからの優れた回答。それはbash Shellで私のために働いています。
# To update/replace the new line string value with the exiting line of the file
MyFile=/tmp/ps_checkdb.flag
`sed -i "${index}s/.*/${newLine}/" $MyFile`
ここ
index
- 行番号
newLine
- 置き換えたい改行文字列。
同様に、以下のコードは、ファイル内の特定の行を読み取るために使用されます。これは実際のファイルには影響しません。
LineString=`sed "$index!d" $MyFile`
ここで
!d
- 行 no 以外の行を削除します。$index
そのため、出力$index
はファイル内の no の行文字列として取得されます。
sed c\
sed c\
実際にはファイルを変更しないため、その出力を一時ファイルに送信してから、一時ファイルを元のファイルに送信する必要がありますcat
。行を指定できるため、パターンの一致は必要ありません。例: sed '1 c\'
=> は 1 行目のテキストを置き換えます。
コマンドを記述するとき、その部分の後のc\
部分は改行し、改行テキストを含める必要があります。
original_file.txt
最後に、テキスト 'foo' で名前が付けられたファイルの 1 行目を「置換」する例を示します。sed 出力を取得して一時ファイルに保存し、一時ファイルを元のファイルに出力していることに注意してください。
# file contents
$ cat original_file.txt
bar
# the replace command
$ sed '1 c\
foo' original_file.txt > temp_file.txt
# output contents of temp_file and overwrite original
$ cat temp_file.txt > original_file.txt
# delete the temp file
$ rm -rf temp_file.txt
パラメータを sed コマンドに渡すこともできます。
test.sh
#!/bin/bash
echo "-> start"
for i in $(seq 5); do
# passing parameters to sed
j=$(($i+3))
sed -i "${j}s/.*/replaced by '$i'!/" output.dat
done
echo "-> finished"
exit
元のoutput.dat:
a
b
c
d
e
f
g
h
i
j
./test.shを実行すると、新しい output.dat が得られます
a
b
c
replaced by '1'!
replaced by '2'!
replaced by '3'!
replaced by '4'!
replaced by '5'!
i
j