BASH: Как использовать Regex Negative Lookahead в команде sed для строки? - PullRequest
0 голосов
/ 07 января 2019

Я не нашел способа использовать это выражение регулярного выражения -. +? (? =,) В команде sed для извлечения части этой строки (используя Lookbehind первого экземпляра символа).

В простом английском я хочу извлечь часть строки, которая находится перед первой запятой. Поскольку в будущем я планирую извлечь конкретное имя файла строки, я не могу полагаться на команду вырезания (мне придется в конечном итоге использовать команду sed),: -

name = 'ОШИБКА 1: /home/rphillips/Desktop/empties/BN23_2303.tif, полоса 1: не удалось вычислить статистику, в выборке не найдено действительных пикселей.'

Это те варианты, которые я использовал, включая test-sed 's / band / rose /', который работал. Однако другие варианты (показанные ниже), которые я использовал, дали пробелы в качестве выходных данных.

while read -r line; do
    name="$line"
    echo $name
    #file_path=$(echo $name | cut -d "," -f 1)
    #file_path=$(echo $name | sed -e '/s\/.+?(?=,)///')
    #file_path=$(echo $name | sed 's/band/rose/')
    file_path=$(echo $name | sed '/s\/.+?(?=, )///')
    #file_path=$(echo $name | grep -P '.+?(?=,)')
    #file_path=$(echo $name | sed 
    #file_path=$(echo $name | awk '/.+?(?=,)/{print $name}'
    echo $file_path
done < "$filename"

Ожидаемый результат - ОШИБКА 1: /home/rphillips/Desktop/empties/BN25_2303.tif

Фактические результаты - ' много пробелов '

Я также заметил, что у выражения regex, которое я использовал, есть разные «совпадения» в соответствии с веб-сайтом Regex101, в зависимости от того, использую ли я Firefox в Windows или Ubuntu 16.04LTS

Windows - https://regex101.com/r/WWGf8F/1 Ubuntu - https://regex101.com/r/NpL2Oa/1

Я не уверен, что из-за этого выражение не распознается sed -e?

Я использовал эти ссылки для различных выражений, используемых в приведенном выше коде

https://likegeeks.com/regex-tutorial-linux/

Как сопоставить «что-нибудь до этой последовательности символов» в регулярном выражении?

https://www.regular -expressions.info / lookaround.html? WLR = 1

https://linux.die.net/man/1/sed

1 Ответ

0 голосов
/ 07 января 2019

В простом английском я хочу извлечь часть строки, которая лежит до первой запятой. Поскольку я планирую извлечь в будущем конкретное имя файла строки, я не могу положиться на команду вырезать (я в конечном итоге придется использовать команду sed)

Строка ввода

ERROR 1: /home/rphillips/Desktop/empties/BN23_2303.tif, band 1: Failed to compute statistics, no valid pixels found in sampling.

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

ERROR 1: /home/rphillips/Desktop/empties/BN25_2303.tif

Прежде чем мы выясним возможные причины, по которым ваша команда sed не работает, давайте рассмотрим вашу настоящую проблему выше. Если вы просто хотите извлечь текст перед первой запятой, тогда все, что вам нужно:

sed 's/,.*//'

(который просто говорит, что удалите все от первой запятой до конца)

Вы также можете использовать обратную ссылку (которая пригодится для достижения конечной цели извлечения имени файла), например,

sed 's/^\([^,][^,]*\).*$/\1/'

(где указано '^' начинаться с начала, \([^,][^,]*\) захватывать весь текст не менее 1 символа, не являющегося запятой, и включать ноль или более дополнительных символов, не являющихся запятыми, .*$ отбрасывать весь текст в конец и \1 замена только захваченным текстом с использованием обратной ссылки)

Чтобы достичь цели извлечения только имени файла, вам нужно только изменить вышеприведенное, чтобы начать захват с первой косой черты, например,

sed 's/^[^/]*\([^,][^,]*\).*$/\1/'

Пример использования / Вывод

$ sed 's/^[^/]*\([^,][^,]*\).*$/\1/' <<< $name
/home/rphillips/Desktop/empties/BN23_2303.tif

Я не уверен, что это заставляет выражение не распознаваться sed -e

sed без опции -E (--regexp-extended) использует регулярные выражения Basic (без учета просмотра или опережения).

Если вы планируете использовать оставшиеся поля значений, разделенных запятыми, вы можете рассмотреть awk для анализа полей. Вы можете легко получить все поля, указав -F разделитель полей и простой цикл.

$ awk -F', ' '{for (i = 1; i <= NF; i++) printf "field %d - %s\n", i, $i}' <<< $name
field 1 - ERROR 1: /home/rphillips/Desktop/empties/BN23_2303.tif
field 2 - band 1: Failed to compute statistics
field 3 - no valid pixels found in sampling.

(вы также можете обрабатывать дальнейшие разборы каждого поля с помощью условия в цикле)

In Bash - расширения параметров - все, что вам нужно

Чтобы не упускать из виду лес для деревьев, так как вы указали bash, если вы просто хотите извлечь имя файла из name, все, что вам нужно, это расширение параметра с удалением подстроки ( сначала справа, а затем слева), например

tmp=${name%%,*}    ## trim to (and including) the 1st comma from the right
echo "/${tmp#*/}"  ## trim to and including the first / from the left
/home/rphillips/Desktop/empties/BN23_2303.tif

(гораздо более эффективный способ)

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

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