Извлечь подстроку с помощью sed, которая останавливается на первом вхождении конца

Извлечь подстроку с помощью sed, которая останавливается на первом вхождении конца

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

echo "This is a test some stuff I want string junk string end" | sed -n 's/.*\(.te.*ng\).*/\1/p' 
returns: test some stuff I want string junk string
I want to return: test some stuff I want string

решение1

грэпподход (требуетПКРЕподдерживать):

s="This is a test some stuff I want string junk string end"
grep -Po 'te.*?ng' <<< $s

Альтернативаперлподход:

perl -ne 'print "$&\n" if /te.*?ng/' <<< $s

Вывод (для обоих подходов):

test some stuff I want string

  • .*?- ?вотнежадныймодификатор, указывает на соответствиеминимальная мода

решение2

Сделайте это в два шага: сначала удалите префикс (если в префиксе присутствовал терминатор), затем удалите все после префикса. Используйте команду, Tчтобы пропустить строку, если она не совпадает:

echo "This is a test some stuff I want string junk string end" |
sed -n 's/.*\(.te.*ng\)/\1/; T; s/\(ng\).*/\1/p'

Либо сначала удалите несоответствующие строки, а затем выполните замену в удобное для вас время.

echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/!d; s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/'

В качестве альтернативы выполните замену и окончательную печать только на совпадающих строках.

echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/ { s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/p; }'

решение3

Я бы посоветовал использовать команду cut в вашем случае.

echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1

Это разрежет строку на три части (до первой, после второй и между «строкой») с помощью -d"" вы можете выбрать, какой шаблон вы хотите использовать в качестве резака, а с помощью -fNumber вы выбираете, какую часть взять. Проблема: «строка» будет удалена Решение:

String=`echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1`
String="$(String) string"
echo $String

Он добавляет разделитель «string», который был удален, в конец переменной $String, которая была определена с помощью выходных данных.

решение4

# Как выполнить жадное сопоставление: "test .*? string" с использованием POSIX sed

sed -e '
   /test.*string/!d;      # non-interesting line
   /^test/s/string/&\
/;                        # append marker after the first substring "string"
   /\n/{P;d;}             # initial portion of pattern space is our result
   s/test/\
&/;D;                     # remove portion before the substring "test"
' yourfile

ДругойPOSIX-lyМетод заключается в том, чтобы удалять подстроку "string" по одной за раз с конца пространства шаблона, пока не останется только одна (после подстроки "test"). Затем остается вывести подстроку "test" на передний план:

sed -e '
   :loop
      s/\(test.*string\).*string.*/\1/
   tloop
   /^test/!s/test/\
&/;/\n/D
' yourfile

Связанный контент