Найти весь текст между $ ... $ разделителями, используя скрипт bash - PullRequest
0 голосов
/ 30 мая 2018

У меня есть текстовый файл, и я пытаюсь получить массив строк, содержащих разделители $ .. $ (формулы LaTeX), используя скрипт bash.Мой текущий код не работает, результат пуст:

#!/bin/bash
array=($(grep -o '\$([^\$]*)\$' test.txt))
echo ${array[@]}

Я проверял это регулярное выражение здесь , он находит совпадения.Я использую следующую тестовую строку:

b5f1e7$bfc2439c621353$d1ce0$629f$b8b5

Ожидаемый результат:

bfc2439c621353 629f

Но echo возвращает пустое значение.Хотя, если я использую '[0-9]\+', это работает:

5 1 7 2439 621353 1 0 629 8 5

Что я делаю не так?

Ответы [ 6 ]

0 голосов
/ 31 мая 2018

Использование регулярного выражения bash:

var="b5f1e7\$bfc2439c621353\$d1ce0\$629f\$b8b5"  # string to var
while [[ $var =~ ([^$]*\$)([^$]*)\$(.*) ]]       # matching
do 
    echo -n "${BASH_REMATCH[2]} "                # 2nd element has the match
    var="${BASH_REMATCH[3]}"                     # 3rd is the rest of the string
done
echo                                             # trailing newline
bfc2439c621353 629f
0 голосов
/ 30 мая 2018

Почему ваш ожидаемый результат задан b5f1e7$bfc2439c621353$d1ce0$629f$b8b5 двумя элементами bfc2439c621353 629f, а не тремя элементами bfc2439c621353 d1ce0 629f?

Вот одна команда grep для ее извлечения:

$ grep -Po '\$\K[^\$]*(?=\$)' <<<'b5f1e7$bfc2439c621353$d1ce0$629f$b8b5'
bfc2439c621353
d1ce0
629f

(Для этого требуется GNU grep, скомпилированный с libpcre для -P)

При этом используется \$\K (эквивалент (?<=\$) для просмотра первых $ и (?=\$) для просмотра впередследующий $. Так как это обходные пути, они не поглощаются grep в процессе, и поэтому можно найти d1ce0.

Вот одна команда POSIX sed для их извлечения:

$ sed 's/^[^$]*\$//; s/\$[^$]*$//; s/\$/\n/g' \
    <<<'b5f1e7$bfc2439c621353$d1ce0$629f$b8b5'
bfc2439c621353
d1ce0
629f

Это не использует нотацию GNU и должно работать в любой POSIX-совместимой системе (например, OS X). Он удаляет начальные и конечные части, которые не нужны, а затем заменяет каждый $ на новую строку.

0 голосов
/ 30 мая 2018

Попробуйте выбраться из фигурных скобок:

tst> grep -o '\$\([^\$]*\)\$' test.txt
$bfc2439c621353$
$629f$

Конечно, тогда вам придется удалить знаки $ (-o печатает весь матч).Вместо этого вы можете попробовать sed:

tst> sed 's/[^\$]*\$\([^\$]*\)\$[^\$]*/\1\n/g' test.txt
bfc2439c621353
629f
0 голосов
/ 30 мая 2018

Как насчет:

grep -o '\$[^$]*\$' test.txt | tr -d '$'

Это в основном выполняет ваш исходный grep (но без скобок, из-за которых он не совпадал), затем удаляет первый / последний символы из каждого совпадения.

0 голосов
/ 30 мая 2018

Вы можете использовать awk с разделителем полей ввода как $:

s='b5f1e7$bfc2439c621353$d1ce0$629f$b8b5'

awk -F '$' '{for (i=2; i<=NF; i+=2) print $i}' <<< "$s"

Обратите внимание, что эта команда awk не проверяет ввод.Если вы хотите, чтобы awk разрешал только допустимые вводы, вы можете использовать эту команду gnu awk с FPAT:

awk -v FPAT='\\$[^$]*\\$' '{for (i=1; i<=NF; i++) {gsub(/\$/, "", $i); print $i}}' <<< "$s"

bfc2439c621353
629f
0 голосов
/ 30 мая 2018

Как насчет этого?

grep -Eo '\$[^$]+\$' a.txt | sed 's/\$//g'

Я использую sed для замены $.

...