У меня есть короткий сценарий Bash, который не передает "-e" в Awk:
str = "Morgenstern"
ex = "-e "
for i in {1..11}
do
echo $(echo $str| awk -v vv = "$i" -v xx = "$ex" 'print xx substr ($0,vv,1)}')
done
результаты должны быть:
-e M
-e o
-e r
и т. д...
фактический результат
M
o
r
Если я изменю ex на «-b», то получу ожидаемый результат (-b M
, -b o
и т. д.).
Я также попробовал жестко закодировать «-e» в операторе Awk с тем же плохим результатом.
Как мне заставить Awk принимать «-e» в качестве параметра или литерала?
См. также бесполезное использование эха
Я голосую за закрытие этого вопроса, потому что автор не использовал shellcheck.net , как указано в теге bash, и не предоставил синтаксически допустимый сценарий оболочки или сценарий awk.
Что бы вы ни пытались сделать, цикл оболочки для вызова echo на выходе выполнения подпроцесса для вызова второго эха, передаваемого по конвейеру в awk, передает переменную, содержащую строку, которая должна быть напечатана из awk и сначала передана обратно в окружение. эхо - это не способ сделать это. Создайте вопрос с минимальным воспроизводимым примером о том, что вы пытаетесь сделать (а не о том, как вы пытаетесь это сделать), чтобы мы могли вам помочь.
Здесь вообще не нужен awk
. Вы можете перебирать символы str
прямо в bash
.
Проблема в избыточном echo
, которому через $(…)
передаются два аргумента, и один он распознает как опцию:
echo -e M
Удалите лишний echo
и избегайте той же проблемы с другим, используя printf
.
str = "Morgenstern"
ex = "-e "
for i in {1..11}
do
printf %s "$str" | awk -v vv = "$i" -v xx = "$ex" '{ print xx substr($0, vv, 1) }'
done
Кроме того, в awk есть циклы for.
str = "Morgenstern"
ex = "-e "
printf %s "$str" | awk -v xx = "$ex" '{
for (i = 1; i <= length($0); i++) {
print xx substr($0, i, 1)
}
}'
В зависимости от того, какой echo
у вас есть, echo -- -e
также может работать; но в любом случае предпочитаю printf
.
Использование цикла awk имеет дополнительное преимущество: оно быстрее, чем цикл for, который я использовал.
Я бы использовал GNU AWK
для этой задачи следующим образом.
str = "Morgenstern"
ex = "-e "
echo "$str" | awk -v x = "$ex" '{print gensub(/(.)/, x"\\1\n", "g", $0)}'
дает результат
-e M
-e o
-e r
-e g
-e e
-e n
-e s
-e t
-e e
-e r
-e n
Объяснение: я сохраняю содержимое ex в переменной x, затем использую строковую функцию gensub, чтобы изменить каждый символ (.
), добавляя содержимое x и новую строку.
Отказ от ответственности: это решение предполагает, что ex не содержит какого-либо символа или его последовательности, имеющей особое значение для второго аргумента gensub (например, &
), если это не так, полностью игнорируйте этот ответ.
(проверено в GNU Awk 5.1.0)
Лишняя группировка регулярных выражений в решении Daweo
— этого достаточно:
str = "Morgenstern"
ex = "-e "
echo "$str" | gawk -v x = "$ex" '{ print gensub(/./, x"&\n", "g") }'
-e M
-e o
-e r
-e g
-e e
-e n
-e s
-e t
-e e
-e r
-e n
В то же время дополнительная группировка должна учитывать не только &
, поскольку и \\0
, и \\1
применимы к сценарию всего с одной группой захвата:
ex='-e \\0\\1'
echo "$str" | gawk -v x = "$ex" '{print gensub(/(.)/, x"\\1\n", "g") }'
-e MMM
-e ooo
-e rrr
-e ggg
-e eee
-e nnn
-e sss
-e ttt
-e eee
-e rrr
-e nnn
Более чистым решением было бы экранирование регулярных выражений x
где-нибудь в разделе BEGIN { }
или использование ванили gsub()
, если только вам не нужна сложная групповая логика захвата.
gsub()
по-прежнему требует некоторого экранирования регулярных выражений, но не так запутанно, как для gensub()
.
Пожалуйста, исправьте ваш пример, чтобы он был работоспособным (без пробелов вокруг
=
, отсутствует{
) и минимальным.