Как я могу получить кавычки, чтобы показать, когда я использую AWK, чтобы найти и заменить?

0

В настоящее время я использую AWK, чтобы найти и заменить часть первых трех вхождений строки. Строка отформатирована как таковая, и в файле есть много таких строк:

func(tempID="39849235",count='12');

Используя эту ссылку , я смог найти метод использования AWK для поиска и замены первых трех экземпляров строки. Я изменил его на то, что мне было нужно, и фрагмент моего скрипта приведен ниже:

id=12349876
awk 'BEGIN {matches=0}
     matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ }
     { print $0 }' filName.py >filName.py.changed

Цель приведенного выше кода - найти соответствие в любой строке, содержащей tempID, и заменить число, назначенное для tempID, значением, содержащимся в переменной с именем $id. Поиск и замена работают хорошо, но, похоже, у меня есть одна проблема: независимо от того, как я это структурирую, выходные данные выводят $ id без кавычек. Я пытался экранировать кавычки и ставить одиночные галочки, но независимо от того, что строка изменена на:

func(tempID=39849235,count='12');

Я попытался удалить двойные кавычки вокруг части замены и структурировать ее как tempID="$id", но, к сожалению, это просто заменяет номер идентификатора на строку $id.

Пожалуйста, дайте мне знать, если есть способ найти и заменить значение tempID и заключить его в кавычки. Я не застрял с AWK, так что любой другой метод с любой другой утилитой, такой как sed, будет работать хорошо.

AndreasKralj
источник

Ответы:

0

В вашей команде есть кавычки, которые интерпретируются и отбрасываются оболочкой, есть кавычки, которые интерпретируются и отбрасываются awk, тогда вам нужны кавычки, которые выжили бы. Вы должны избежать их:

id=12349876
awk 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ }
 { print $0 }' filName.py >filName.py.changed              # ^^  here ^^

Объяснение. Ваша оригинальная команда похожа

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                      ^^   ^^                            ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^              ^
#     this variable is expanded by the shell and gets to awk as its value            ^^^

И это улучшенная команда:

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                        ^^   ^^                              ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^                  ^
#     these quotes will appear in the output thanks to being escaped                ^        ^
#     this variable is expanded by the shell and gets to awk as its value              ^^^

Чтобы уменьшить безумие в кавычках, вы можете использовать -vопцию для передачи переменной awk. Тогда вам не нужно закрывать и открывать среднюю последовательность одинарных кавычек только для расширения оболочки $id. Вместо того, чтобы без кавычек (как awkон видит) idрасширяется awkсамостоятельно. Двойные кавычки, которые мы должны добавить, должны быть экранированы, как и раньше:

id=12349876
awk -v id="$id" 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\""id"\""); matches++ }
 { print $0 }' filName.py >filName.py.changed
Камил Мачоровский
источник
Большое спасибо! Awk -v был именно тем, что мне было нужно!
AndreasKralj
0

Чтобы достичь того, что вы хотите сделать, вам необходимо:

Для двойных кавычек:

  • AWK: избегать двойных кавычек "внутри других двойных кавычек.
    $1 $2=> foobar
    $1" __"$2"__"=> foo __bar__
    $1" \""$2"\""=>foo "bar"

Для одинарных кавычек:

  • Оболочка: Выйти из '…'всего вашего скрипта awk, используя другой набор '…'внутри него.
    'escaped 'unescaped' escaped'
    '$LINUX '$OSTYPE' $CPUTYPE'=>$LINUX linux-gnu $CPUTYPE

  • Shell: Escape 'вы хотите, чтобы печататься буквально.
    'apostrophe that'\''s literal'=>apostrophe that's literal

Например

echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'
Аризона
источник
Другой способ - восьмеричные или шестнадцатеричные коды в двойных кавычкахecho foo bar | awk '{print "\x22"$1"\042","\x27"$2"\047"}'
Пауло,