Как я могу заменить текст после определенного слова с помощью sed вместо изменения всей строки?

Я пытаюсь заменить текст после определенного слова, но sed меняет всю строку. Извлечь одно слово после определенного слова

Входной файл: sample.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 : Я хочу изменить только одно слово после Имя хоста:

#!/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
0
23.03.2017, 12:24
3 ответа

. * соответствует все в остальной части строки, поэтому все заменено. Если вы хотите заменить все до следующего пробела, вам понадобится [^] вместо .`

0
28.01.2020, 02:46

Ваша проблема не воспроизводится:

$ 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

Оба sed и perl можно комбинировать с -i для редактирования на месте, если это необходимо.

0
28.01.2020, 02:46

Когда вы выполняете интерполяцию двойных кавычек на rhs 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
1
28.01.2020, 02:46

Теги

Похожие вопросы