Добавьте BEGIN { OFS="\t" }
в начало сценария awk и измените {print }
на {print $1, $2, $3, $4}
. Это изменит разделитель полей вывода awk на tab с пробела по умолчанию.
Для n столбцов можно использовать {$1 = $1; print}
вместо {print}
. Я не уверен, как это работает внутри, но при тестировании это работает.
Компактнее и легче:
sed 'G;/^Value=/s/=.*\nName=Tom/=42/;s/\n.*//;h' file
Это добавляет к каждой строке предыдущую строку из пробела. Для строк Value=
значение заменяется, если Name=Tom
было в ячейке удержания. В противном случае добавленная строка удаляется, а строка сохраняется в резервном пространстве для следующего цикла.
сawk
:
awk 'prev ~ /^Name=(Tom|Anything)$/ && /^Value=/ {$0 = "Value=123"}
{print; prev = $0}'
Или с именем и новым значением , сохраненным в переменной:
export NAME=Tom VALUE=123
awk 'prev == "Name=" ENVIRON["NAME"] && /^Value=/ {
$0 = "Value=" ENVIRON["VALUE"]
}
{print; prev = $0}'
Для sed
эквивалентом будет что-то вроде:
sed -e 'x;/^Name=Tom$/{g;/^Value/s/=.*/=123/;h;b' -e '}' -e g
Хотя, как обычно, он короче, но значительно менее разборчив, чем с awk
. Кроме того, для работы с произвольными значениями, хранящимися в переменных, sed
не имеет эквивалента awk
ENVIRON
или возможности простого сравнения строк (в отличие от сопоставления регулярных выражений ). поэтому вам нужно предварительно -обработать значения переменных, если только вы не можете гарантировать, что переменные не содержат специальных символов для sed
.
sed -e "x;/^Name=$NAME\$/{g;/^Value/s/=.*/=$VALUE/;h;b" -e '}' -e g
Может быть уязвимость, связанная с внедрением команд (, по крайней мере, с GNU sed
), если $NAME
и $VALUE
не контролируются жестко.
sed -e '
/^Name=Tom$/!b
$!N
/\(\nValue\)=.*/s//\1=NEW_VALUE/
P;D
' data.inp
Name=Tom
Value=NEW_VALUE
Name=Tom
Name=Harry
Value=20