В настоящее время я использую 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, тоже будет работать нормально.
решение1
В вашей команде есть кавычки, интерпретируемые и удаляемые оболочкой, есть кавычки, интерпретируемые и удаляемые 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
. Вместо этого unquoted (как 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
решение2
Чтобы достичь желаемого, вам необходимо:
Для двойных кавычек:
- AWK: Экранирование двойных кавычек
"
внутри других двойных кавычек.
$1 $2
=>foobar
$1" __"$2"__"
=>foo __bar__
$1" \""$2"\""
=>foo "bar"
Для одинарных кавычек:
Shell: Выйдите
'…'
из всего вашего скрипта 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'