Sed для вывода только первого совпадения с образцом в строке

В дополнение к возобновлению S3 buttersink , btrbk поддерживает:

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

Изменить: I С тех пор стало известно, что передача отдельных снимков не возобновляется с помощью btrbk , однако он будет иметь дело с резервным целевым объектом, переходящим в автономный режим (перезапуск передачи прерванного снимка).

6
01.08.2017, 16:22
6 ответов

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

Поскольку разделителем здесь является только один символ, мы можем использовать группу перевернутых квадратных скобок для соответствия чему угодно, кроме кавычек, т. е. [^"], а затем повторять это для соответствия ряду символов, которые не являются кавычками.

$ echo '... "foo"... "bar"...' | sed 's/[^"]*"\([^"]*\)".*/\1/'
foo

Другой способ — просто удалить все до первой кавычки, а затем удалить все, начиная с (новой )первой кавычки:

$ echo '... "foo"... "bar"...' | sed 's/^[^"]*"//; s/".*$//'
foo

В регулярных выражениях Perl спецификаторы *и +можно сделать не -жадными, добавив знак вопроса, поэтому .*?будет что угодно, но как можно меньше символов/байтов.

12
27.01.2020, 20:20

Я не буду утомлять вас классическим предупреждением против использования простых регулярных выражений для разбора HTML. Достаточно сказать, что вместо этого вы должны использовать специальный парсер. Тем не менее, проблема здесь в том, что sedиспользует жадное сопоставление. Таким образом, он всегда будет соответствовать самой длинной строке. Это означает, что ваш .*продолжается вечно и соответствует всей строке.

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

$ perl -pe 's/.*?"(.*?)".*/$1/' file
data1

Так как sedне поддерживает не--жадные совпадения, вам понадобится еще одна хитрость. Проще всего было бы использовать подход «без кавычек» в ответе ikkachu . Вот альтернатива:

$ rev file | sed 's/.*"\(.*\)".*/\1/' | rev
data1

Это просто переворачивает файл (rev), использует ваш первоначальный подход, который теперь работает, поскольку 1-е вхождение теперь является последним, а затем снова переворачивает файл.

4
27.01.2020, 20:20

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

cat data | grep -Po '(?<=href=").*?(?=")' | head -n1
2
27.01.2020, 20:20

Вот несколько способов, которыми вы можете извлечь данные1 из вашего ввода:

grep -oP '^[^"]*"\K[^"]*'

sed -ne '
   /\n/!{y/"/\n/;D;}
   P
'

perl -lne '/"([^"]*)"/ and print($1),last'
4
27.01.2020, 20:20

Хотя Вопрос не помечен тегом awk, но почему бы не использовать его просто так, как есть:

awk -F\" '{print $2}' infile.txt 
3
27.01.2020, 20:20

Если вы хотите поместить sedв первое из нескольких совпадений в строке, просто сначала измените первое совпадение:

echo abcmatchdefmatchghimatchjkl | \
sed -e "s/match/m#1#atch/" \
 -e "s/^.*m#1#atch/match/" 
gives the result
matchdefmatchghimatchjkl

Это может быть изменено, например, для. второй матч:

echo abcmatchdefmatchghimatchjkl | sed \
 -e "s/match/m#1#atch/" \
 -e "s/match/m#2#atch/" \
 -e "s/^.*m#2#atch/match/" 

дает результат

matchghimatchjkl
0
14.08.2020, 14:25

Теги

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