Изменение переменной оболочки с помощью регулярного выражения (bash)

Например, у меня есть переменная оболочки. а = "большой маленький человек". Как использовать регулярное выражение в bash, чтобы распечатать переменную только с заглавной буквы среднего слова? (большой МАЛЕНЬКИЙ человечек)

Я могу сделать это, разделив переменную на 3 переменные и затем расширив их в эхе. Например, first=${a%*} и т. д. Но как мне сделать это за один раз с одним регулярным выражением?

Можно ли сделать это в одну строку? Использование операторов заглавных букв (^)

0
09.02.2019, 09:32
3 ответа

сед

Предполагая, что вы используете GNU sed:

$ sed -E 's/(\w+) (\w+) (\w+)/\1 \U\2\E \3/' <<< 'big little man'
big LITTLE man

Эта команда использует специальные последовательности GNU\Uи \E, которые переводят последующие символы в верхний регистр и отменяют преобразование регистра соответственно.

авк

Не работая с регулярными выражениями, awkпредоставляет еще один удобный способ использовать заглавные буквы в одном слове:

$ awk '{print($1, toupper($2), $3)}' <<< 'big little man'
big LITTLE man

баш

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

$ (read -a words; echo "${words[0]} ${words[1]^^} ${words[2]}") <<< 'big little man'
big LITTLE man

Здесь ^^преобразует второй элемент нашего массива (, то есть второе слово )в верхний регистр. Эта функция была представлена ​​в Bash 4.

5
28.01.2020, 02:30

Я не думаю, что вы можете сделать это с bashоператорами расширения за один раз. Вы могли бы с zsh:

set -o extendedglob # for (#m)

b=${a/(#m) * /${(U)MATCH}}

или:

b=${(S)a/(#b)(*) (*) (*)/$match[1] ${(U)match[2]} $match[3]}

Где:

  • (#m)делает совпадающую строку доступной в$MATCH
  • (#b)включает назад -ссылки
  • ${(U)var}(также$var:u)превращается в верхний регистр (предшествует bash${var^^pattern}на десятилетия ).
  • (S)включает не-жадное сопоставление.
3
28.01.2020, 02:30

В соответствии с запросом, сделать это в bashв одной строке, используя${variable^^}:

$ a="big little man"
$ [[ "$a" =~ ^([^ ]+)\ ([^ ]+)\ (.*) ]] && a="${BASH_REMATCH[1]} ${BASH_REMATCH[2]^^} ${BASH_REMATCH[3]}"
$ echo "$a"
big LITTLE man

Сопоставляется регулярному выражению ([^ ]+)\ ([^ ]+)\ (.*)со строкой в ​​$a. Если он совпадает, то содержит три подстроки, разделенные пробелами. Первая и вторая подстроки будут любой строкой, не содержащей пробела, а третья подстрока будет оставшимся битом строки.

Если выражение совпадает, значение $aперезаписывается так, чтобы вторая подстрока была в верхнем регистре.

Предполагается, что исходная строка начинается с символа пробела, отличного от -.

4
28.01.2020, 02:30

Теги

Похожие вопросы