전체 줄을 변경하는 대신 sed를 사용하여 특정 단어 뒤의 텍스트를 어떻게 바꿀 수 있습니까?

전체 줄을 변경하는 대신 sed를 사용하여 특정 단어 뒤의 텍스트를 어떻게 바꿀 수 있습니까?

특정 단어 뒤의 텍스트를 바꾸려고 하는데 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:한 단어만 변경하고 싶은 후에 모든 단어를 변경하는 다음 스크립트를 작성했습니다.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을 모두 결합할 수 있습니다 .

관련 정보