bashスクリプトでファイルの行全体を置き換えたい状況があります。行番号は常に同じであるため、ハードコードされた変数になる可能性があります。
その行の一部の文字列を置き換えようとしているのではなく、その行全体を新しい行に置き換えたいだけです。
これを行うためのbashメソッド(または.shスクリプトにスローできる単純なもの)はありますか?
bashスクリプトでファイルの行全体を置き換えたい状況があります。行番号は常に同じであるため、ハードコードされた変数になる可能性があります。
その行の一部の文字列を置き換えようとしているのではなく、その行全体を新しい行に置き換えたいだけです。
これを行うためのbashメソッド(または.shスクリプトにスローできる単純なもの)はありますか?
回答:
最大ではありませんが、これはうまくいくはずです:
sed -i 'Ns/.*/replacement-line/' file.txt
where N
は、ターゲットの行番号に置き換える必要があります。これにより、元のファイルの行が置き換えられます。変更したテキストを別のファイルに保存するには、-i
オプションをドロップします。
sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
sed: -e expression #1, char 26: unknown option to ``s'
そして私の行は:sed -i '7s/.*/<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</param-value>/' $TCE_SVN_HOME\trunk\tce\EWC\WebContent\WEB-INF\web.xml
です。何か案が?
/
置換テキストのそれぞれは、s
エスケープ(\/
)されていない限り、コマンドの終了スラッシュとして解釈されます。ただし、最も簡単な方法は、使用されていない別の文字を区切り文字として選択することです。たとえば、sed -i '7s{.*}{<param-value>http://...}' $TCE_SVN_HOME/trunk...
。
s
。区切り文字を決定します だから、例えば使用するようにコマンドを変更するには#
:それはこのようなものだsed -i '7s#.*#<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</param-value>#'
-e
if -i
が指定されている必要があります。したがって、正しいコマンドは次のようになりますsed -e 'Ns/.*/replacement-line/' -i '' 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
。
sed -e "s/.../.../" /dir/file > /dir/temp_file
sed -e "s/.../.../" /dir/file > /dir/file
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回実行されます。
シェルがのようなものを解釈しようとしないようにするには、AWKプログラムを一重引用符で囲む必要があります$0
。
編集:以下のコメントで@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は、このような簡潔なプログラムを許可するように設計されています。
awk 'NR==4 {$0="different"} { print }' input_file.txt
。
awk 'NR==4 {$0="different"}1' input_file.txt
1
は何をしますか?(注:私はそれをテストしましたが、実際に機能します。方法がわからないだけです。)
このテストファイル(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/
sed '1 cnewline text' test.txt
同様にそれを行います。
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には解決策はありません。 ヌル文字(\ 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"
}
チェプナーからの素晴らしい答え。それは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`
here
index
-Line
newLine
no-置き換えたい新しい行ストリング。
同様に、以下のコードは、ファイル内の特定の行を読み取るために使用されます。これは実際のファイルには影響しません。
LineString=`sed "$index!d" $MyFile`
ここで
!d
-行no以外の行を削除します。そのため、ファイル$index
にnoの行ストリングとして出力を取得$index
します。
${newline}
ですか?
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
line=5; sed -i "${line}s/.*/replaced by '$i'!/" output.dat