183

ファイル内の行全体を bash スクリプトで置き換えたい状況があります。行番号は常に同じであるため、ハードコーディングされた変数にすることができます。

その行の一部の文字列を置き換えようとしているのではなく、その行を完全に新しい行に置き換えたいだけです。

これを行うための bash メソッド (または .sh スクリプトにスローできる単純なもの) はありますか。

4

11 に答える 11

277

最大ではありませんが、これはうまくいくはずです:

sed -i 'Ns/.*/replacement-line/' file.txt

どこNをターゲット行番号に置き換える必要があります。これにより、元のファイルの行が置き換えられます。変更したテキストを別のファイルに保存するには、-iオプションをドロップします。

sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
于 2012-06-21T19:26:37.013 に答える
45

私は実際にこのスクリプトを使用して、しばらく前に当社の 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

于 2012-06-21T19:32:24.753 に答える
26

行 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 は、このような簡潔なプログラムを許可するように設計されています。

于 2012-06-21T19:27:12.750 に答える
20

このテスト ファイル (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/

于 2012-06-21T19:30:30.897 に答える
8

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
于 2012-06-21T19:29:21.990 に答える
3

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 の行文字列として取得されます。

于 2014-04-24T12:36:21.153 に答える
1

行を次のように置き換えます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
于 2021-12-13T23:36:58.717 に答える
-2

パラメータを 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
于 2017-12-08T08:14:36.360 に答える