Передача "-e" в качестве параметра awk приводит к неожиданным результатам

У меня есть короткий сценарий 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» в качестве параметра или литерала?

Пожалуйста, исправьте ваш пример, чтобы он был работоспособным (без пробелов вокруг =, отсутствует {) и минимальным.

Ry- 23.07.2024 05:03

См. также бесполезное использование эха

tripleee 23.07.2024 13:48

Я голосую за закрытие этого вопроса, потому что автор не использовал shellcheck.net , как указано в теге bash, и не предоставил синтаксически допустимый сценарий оболочки или сценарий awk.

Ed Morton 23.07.2024 15:04

Что бы вы ни пытались сделать, цикл оболочки для вызова echo на выходе выполнения подпроцесса для вызова второго эха, передаваемого по конвейеру в awk, передает переменную, содержащую строку, которая должна быть напечатана из awk и сначала передана обратно в окружение. эхо - это не способ сделать это. Создайте вопрос с минимальным воспроизводимым примером о том, что вы пытаетесь сделать (а не о том, как вы пытаетесь это сделать), чтобы мы могли вам помочь.

Ed Morton 23.07.2024 15:08

Здесь вообще не нужен awk. Вы можете перебирать символы str прямо в bash.

chepner 23.07.2024 17:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
61
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Проблема в избыточном 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.

tripleee 23.07.2024 13:49

Использование цикла awk имеет дополнительное преимущество: оно быстрее, чем цикл for, который я использовал.

C0ppert0p 23.07.2024 20:25

Я бы использовал 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().

Другие вопросы по теме