特定の単語の後のテキストを変更しようとしていますが、行sed
全体が変わっています。特定の単語の後の単語の抽出
入力ファイル:サンプル.txt
My Hostname:internal is valid.
some log file entries
some log file entries
出力:
My Hostname:mmphate
some log file entries
some log file entries
予想出力:
My Hostname:mmphate is valid.
some log file entries
some log file entries
Hostname:
1つの単語だけを変更したい場合は、すべての単語を変更する次のスクリプトを作成しました。Hostname:
#!/usr/bin/env bash
HOST=$(curl -s 169.254.169.254/latest/meta-data/local-hostname)
while getopts ih opt
do
case $opt in
i)
;;
h)
sed -e "s/Hostname:.*/Hostname:$HOST/g" sample.txt
echo "Updated Hostname: $HOST"
;;
esac
done
答え1
時右回転入力は特別にエラーを引き起こす可能性があり、悪い場合はエラーはありませんが、まったく予期しない結果が生じる可能性があるため、s///
入力を適切にエスケープするように注意する必要があります。sed
たとえば、$HOST
アンパサンドまたはを含めると&
どうなるか考えてみましょう/
。
# definitions
TAB=`echo 'x' | tr 'x' '\011'`; # tab
SPC=`echo 'x' | tr 'x' '\040'`; # space
eval "`echo 'n=qsq' | tr 'qs' '\047\012'`"; # newline
# construct regexes
s="[$SPC$TAB]"; # spc/tab regex
S="[^$SPC$TAB]"; # nonwhitespace regex
# perform the escape operation
esc() {
set -- "${1//\\/\\\\}" # escape backslash to prevent it from dissolving
set -- "${1//\//\\\/}" # escape forward slash to prevent from clashing with delimiters
set -- "${1//&/\\&}" # escape ampersand since it has a specific meaning rhs of s//
set -- "${1//\"/\\\"}" # escape double quotes in an interpolation
set -- "${1//$n/\\$n}" # escape newlines
printf '%s\n' "$@"
}
# grab the hostname
HOST=$(curl -s 169.254.169.254/latest/meta-data/local-hostname)
# escape hostname to enable it to be used seamlessly on the rhs of s///
host_esc=$(esc "$HOST")
# and then...
sed -e "s/\(${s}Hostname\):$S$S*/\1:$host_esc/g" sample.txt
答え2
.*
行の残りの部分にあるすべてのアイテムと一致するため、すべてのアイテムが置き換えられます。すべてを次のスペースに置き換える必要があります[^ ] instead of
。 `
答え3
問題を再現できません:
$ name="george"
$ echo "My Hostname:internal is valid." |sed "s/internal/$name/g"
My Hostname:george is valid.
internal
以下のログエントリにも対応する単語がある場合は、My Hostname
次のように使用できます。
$ sed -r "s/(My Hostname:)(internal)/\1$name/g" file4
My Hostname:george is valid.
internal log entry
log internal entry
機能しない場合、または何らかの理由で期待どおりに機能しない場合はGNU Sed
、sed
この簡単な交換のためにいつでもperl
どこでも同じ方法で動作するように切り替えることができます。
$ cat file4
My Hostname:internal is valid.
internal log entry
log internal entry
$ perl -pe "s/(My Hostname:)(internal)/\1$name/g" file4
My Hostname:george is valid.
internal log entry
log internal entry
-i
必要に応じて、内部編集用にsedとperlの両方を組み合わせることができます。