Заменить слово строки, если найдено

Мне дали файл. Если строка имеет "xxx" в качестве третьего слова, то мне нужно заменить его на "yyy". Мой окончательный вывод должен иметь все исходные строки с измененными строками.Входной файл

abc xyz mno
xxx xyz abc
abc xyz xxx
abc xxx xxx xxx

Требуемый выходной файл должен быть-

abc xyz mno
xxx xyz abc
abc xyz yyy
abc xxx yyy xxx

Я пытался-

grep "\bxxx\b" file.txt | awk '{if ($3=="xxx") print $0;}' | sed -e 's/[^ ]*[^ ]/yyy/3'

но это дает выход как

abc xyz yyy
abc xxx yyy xxx

4 ответа

После простого awk может помочь вам в том же.

awk '$3=="xxx"{$3="yyy"} 1'   Input_file

Вывод будет следующим.

abc xyz mno
xxx xyz abc
abc xyz yyy
abc xxx yyy xxx

Пояснение: Проверка состояния здесь, если $3 3-е поле равно строке xxx затем настройка $3значение в строку yyy, Тогда упомяну 1 там, так как awk работает по методу условия, а затем по действию. Я ставлю условие ИСТИНА здесь, упоминая 1 здесь и НЕ упоминать какие-либо действия здесь, так что будет печать текущей строки по умолчанию (либо с измененным 3-м полем, либо с новым 3-м полем).

sed решение:

sed -E 's/^(([^[:space:]]+[[:space:]]+){2})apathy\>/\1empathy/' file

Выход:

abc xyz mno
apathy xyz abc
abc xyz empathy
abc apathy empathy apathy

Чтобы изменить файл на месте добавить -i опция: sed -Ei ....

Ravinder уже предоставил вам самое короткое решение для awk.

В sed будет работать следующее:

sed -E 's/(([^ ]+ ){2})xxx/\1yyy/'

Или если ваш сед не включает -EВы можете использовать более болезненную запись BRE:

sed 's/\(\([^ ][^ ]* \)\{2\}\)xxx/\1yyy/'

И если у вас есть настроение справиться с этим в одиночку, может что-то подобное:

while read -r line; do
  read -r -a a <<<"$line"
  [[ "${a[2]}" == "xxx" ]] && a[2]="yyy"
  printf '%s ' "${a[@]}"
  printf '\n'
done < input.txt

В общем то awk команда может выглядеть так

awk '{command set 1}condition{command set 2}' file

command set 1 будет выполняться для каждой строки в то время как command set 2 будет выполнено, если условие, предшествующее этому, является истинным.

Мой окончательный вывод должен иметь все исходные строки с измененными строками

В твоем случае

 awk 'BEGIN{print "Original File";i=1}
      {print}
      $3=="xxx"{$3="yyy"}
      {rec[i++]=$0}
      END{print "Modified File";for(i=1;i<=NR;i++)print rec[i]}'file

должен решить это.

объяснение

$3 третье разделенное пробелами поле в awk, Если это соответствует "xxx"затем он заменяется. Сначала выведите неизмененные строки, сохраняя измененные строки в массиве. В конце выведите измененные строки. BEGIN а также END блоки выполняются только в начале и конце соответственно. NR является встроенной переменной awk, которая обозначает количество записей, обработанных до настоящего момента. Так как он используется в END Блок это должно дать нам общее количество записей.

Все хорошо :-)

Другие вопросы по тегам