Использование регулярных выражений в скриптах bash - PullRequest
0 голосов
/ 28 марта 2019

Я пытаюсь использовать регулярное выражение в операторе if в bash-скрипте, но получаю разные значения.

Сценарий:

#!/bin/bash

a="input2.txt"

paramCheck(){
  while read -r line; do
    d=( $line )
    e=${d[@]:1}
    for i in "$e"; do
      if [ "$i" == $[st][0-9] ]; then
         echo "$i"
      fi
    done
  done < "$a"
}

echo `paramCheck`

Текстовый файл:

add $s1 $s2 $s3
sub $t0 
sub $t1 $t0 
addi $t1 $t0 $s5

Прогнозируемые результаты:

$s1 $s2 $s3 $t0 $t1 $t0 $t1 $t0 $s5

Фактический результат: ничего не распечатано.

Ответы [ 2 ]

1 голос
/ 28 марта 2019

Вот один из способов сделать это, используя различные стандартные утилиты:

$ cut -d' ' -f2- infile | grep -o '\$[st][[:digit:]]' | paste -sd ' '
$s1 $s2 $s3 $t0 $t1 $t0 $t1 $t0 $s
  • cut удаляет первый разделенный пробелами столбец
  • grep находит все совпаденияшаблон и печатает их по одному на строку
  • paste получает вывод в одну строку

В чистом Bash:

#!/usr/bin/env bash

while read -ra line; do
    for word in "${line[@]:1}"; do
        [[ $word == \$[st][[:digit:]] ]] && printf '%s ' "$word"
    done
done < 'input2.txt'
  • читает непосредственно в массив с read -a
  • без промежуточного присваивания, зацикливание непосредственно над элементами "${line[@]:1}"
  • использование [[ ]] для сопоставления с образцом, экранирование $, использование locale-safe [[:digit:]] вместо [0-9]
  • используйте printf вместо echo для подавления разрывов строк

Обратите внимание, что это добавит завершающий пробел.


Несколько указателей для вашего кода:

  • d=( $line ) опирается на разделение слов и зависит от расширения имени файла;если у вас есть слово * в $line, оно будет расширено до всех файлов в каталоге.
  • e=${d[@]:1} назначит второй и последующие элементы массива в одну строку - теперь мы не будембольше нет массива.Чтобы сохранить массив, используйте e=("${d[@]:1}").
  • for i in "$e" теперь имеет $e, содержащий все элементы в одной строке, а кавычки подавляют разбиение слов, поэтому для первой строки это будетположить все $s1 $s2 $s3 в i вместо $s1.Намерение, вероятно, for i in $e, но это опять-таки зависит от разделения слов и расширения глобуса;вместо этого используйте массив.
  • [ ] не поддерживает сопоставление с образцом, вместо этого используйте [[ ]].$ необходимо экранировать.
  • Шаблоны глобуса (используемые здесь) являются , а не регулярными выражениями.Обратитесь к статье «Шаблоны» в ссылках для хорошего обзора различий.
  • Bash понимает как == и = в [ ], но == не переносимо (как в"POSIX conformant") - это хорошая привычка вместо этого использовать =[[ ]], это спорно, что использовать, так как [[ ]] не является переносимым сам.

Ссылки:

1 голос
/ 28 марта 2019

Вы должны использовать двойные скобки для соответствия регулярному выражению и избегать доллара, так как это специальный символ bash.Заменить

if [ "$i" == $[st][0-9] ]; then

на

if [[ "$i" = \$[st][0-9] ]]; then

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...