ファイル内の1行全体を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
は現在の完全なレコードを表します($1
はレコードの最初のフィールドなどです。デフォルトでは、フィールドは行の単語です)。
したがって、現在の行番号が4の場合、文字列 "different"を表示しますが、それ以外の場合は変更せずに行を表示します。
AWKでは、{ }
で囲まれたプログラムコードは各入力レコードで1回実行されます。
シェルが$0
のようなものを解釈しようとしないようにするには、AWKプログラムを一重引用符で囲む必要があります。
編集:以下のコメントで@chepnerから短く、よりエレガントなAWKプログラム:
awk 'NR==4 {$0="different"} { print }' input_file.txt
レコード(行番号)4の場合のみ、レコード全体を文字列 "different"で置き換えます。次に、入力レコードごとにレコードを印刷します。
明らかに私のAWKのスキルは錆びています!ありがとう、@ chepner。
編集:そしてまた@デニスウィリアムソンからさらに短いバージョンを参照してください:
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.
次のコマンドは最初の行を "newline text"に置き換えます
$ 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では解決策はありません。 null文字(\ 0)を含む文字列をBashの変数に代入する しかし、通常のテキストファイルにはあります。ヌル文字なし\ 0
Perlが良い選択でしょう
Perl -ne 'if($.==N){print"xxx\n"}elsif($.==M){print"yyy\n"}else{print}' < orig-file > new-file
# Replace the line of the given line number with the given replacement in the given file.
function replace-line-in-file() {
local file="$1"
local line_num="$2"
local replacement="$3"
# Escape backslash, forward slash and ampersand for use as a sed replacement.
replacement_escaped=$( echo "$replacement" | sed -e 's/[\/&]/\\&/g' )
sed -i "${line_num}s/.*/$replacement_escaped/" "$file"
}
Chepnerからの素晴らしい答え。それはbashシェルで私のために働いています。
# 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
- 行番号$index
以外の行を削除します。したがって、出力はファイル内のno $index
の行ストリングとして取得されます。
私が使ったMacでは
sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name