Я пытаюсь вставить переменный текст после другого переменного текста на определенной строке. Ниже представлена моя попытка на данный момент, насколько я могу судить, если я смогу экранировать кавычки так, awk
чтобы переменная была видна и все еще применялась, то это должно сработать, но я понятия не имею, как это сделать:
#!/bin/sh
VAR=$(head -n1 ~/Scripts/tmp/file.txt)
VAR1=$(head -n1 ~/Scripts/tmp/file1.txt)
awk '/$VAR/ { print; print "$VAR1"; next }1' ~/Scripts/tmp/file.txt
решение1
Чтобы передать строки в скрипт awk, передайте их через переменные окружения.
export VAR VAR1
awk '
1
$0 == ENVIRON["VAR"] {print ENVIRON["VAR1"]}
' ~/Scripts/tmp/file.txt
Я реорганизовал ваш скрипт, чтобы упростить логику. Я также заменил сопоставление регулярных выражений сравнением строк: при сопоставлении регулярных выражений $VAR
будет рассматриваться как регулярное выражение, оно не будет выполнять сравнение строк. И /$VAR/
даже не будет использовать значение VAR
(это синтаксис Perl, а не awk), которое вам match($0, VAR)
для этого понадобится.
Примечание о некоторых других решениях, которые на самом деле не работают (они работают только в том случае, если переменные не содержат никаких специальных символов; какой именно символ является специальным, зависит от метода):
awk -v awkvar="$VAR" '$0 == awkvar …'
расширяет обратные косые черты в содержимом строки.awk "/$VAR/" …
заставляет оболочку развернуть значениеVAR
как фрагмент awk. Например, еслиfile.txt
содержит^/ {system("touch ~/naughty")} /
, то командаtouch ~/naughty
выполняется.
Альтернативный подход — заставить awk прочитать все файлы.
awk '
BEGIN { VAR1 = getline <"~/Scripts/tmp/file1.txt"; }
NR == 1 {VAR = $0}
1
$0 == ENVIRON["VAR"] {print ENVIRON["VAR1"]}
' ~/Scripts/tmp/file.txt
решение2
Одно из возможных решений AWK:
awk '/'$VAR'/ { print; print "'$VAR1'"; next }1'
разбейте кавычки вокруг всех ваших внешних переменных.
Другое возможное решение, как и в другом посте, с передачей переменных, — это передача VAR1 как переменной awk, но я думаю, что вам все равно нужно сделать экранирование блока одинарных кавычек для шаблона с использованием VAR:
awk -v var=$VAR1 '/'$VAR'/ { print; print var; next }1'
Вместо этого вы можете попробовать sed :) он специально разработан для такого рода замены.
sed "s/$VAR.*/\0\n$VAR1/" ~/Scripts/tmp/file.txt
Если вы можете иметь несколько экземпляров VAR в одной строке, то добавьте g в конец команды sed (глобальная), чтобы она не останавливалась на первом найденном совпадении:
sed "s/$VAR.*/\0 $VAR1/g" ~/Scripts/tmp/file.txt
ВАЖНО!: убедитесь, что символ «/» не встречается в переменной VAR или VAR1. Если это так, вам нужно экранировать его для awk или sed. В качестве альтернативы с помощью sed вы можете изменить разделитель для команды на что-то другое, например, «;», например:
sed "s;$VAR.*;\0\n$VAR1;" ~/Scripts/tmp/file.txt
Объяснение команды sed:
Мы используем двойные кавычки вместо одинарных вокруг команды sed, чтобы переменные, такие как VAR и VAR1, были заменены их значениями. Это происходит до того, как команда будет выполнена sed, поэтому, если / может присутствовать в содержимом переменной, вам нужно обратиться к ней (это справедливо и для awk).
's' указывает на то, что вы пишете команду подстановки в форме:
s/<шаблон>/<шаблон замены>/
'/' сразу после s является разделителем, который будет использоваться для разделения разделов команды. поэтому, если вы поместите ;, вы должны использовать ; везде, как показано выше. Шаблоном для сопоставления будет содержимое переменной $VAR. Шаблон подстановки - \0, что означает вывод того, что совпало с шаблоном, новой строки '\n' и содержимого VAR2.
УПС, не увидел части о строке ниже... фиксированные шаблоны.
решение3
Если вы хотите использовать awk
, вам необходимо передать bash
переменную awk
с -v
опцией :
awk -v v=$VAR -v v1=$VAR1 '/v/ { print; print v1; next }1' ~/Scripts/tmp/file.txt
Но проверьте ответ Роба для более правильного и подробного решения.