Extraia uma substring com sed que pare na primeira ocorrência do final

Extraia uma substring com sed que pare na primeira ocorrência do final

Tenho uma string de onde preciso extrair uma substring, mas o final da minha regex se repete. Eu gostaria que o sed parasse na primeira instância do final do meu regex, assim como as funções instr() em muitos idiomas retornam a primeira instância. Exemplo:

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

Responder1

grepabordagem (requerPCREapoiar):

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

Alternativaperlabordagem:

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

A saída (para ambas as abordagens):

test some stuff I want string

  • .*?- ?aqui estánão gananciosomodificador, diz para combinarmoda mínima

Responder2

Faça isso em duas etapas: primeiro remova o prefixo (caso o terminador esteja presente no prefixo) e depois remova tudo após o prefixo. Use o Tcomando para pular uma linha se ela não corresponder:

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

Como alternativa, exclua primeiro as linhas não correspondentes e, em seguida, execute a substituição quando quiser.

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

Alternativamente, realize as substituições e a impressão final apenas nas linhas correspondentes.

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

Responder3

Eu sugeriria usar o comando cut no seu caso

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

Isso cortaria o barbante em três partes (antes da primeira, depois da 2. E entre o 'corda') com -d"" você pode escolher qual padrão deseja usar como cortador e com -fNumber você escolhe qual parte deseja pegar. Problema: a 'string' será removida Solução:

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

Ele adiciona o delimitador "string" que foi removido ao final da variável $String que foi definida com a saída

Responder4

# Como realizar a correspondência gananciosa: "test .*? string" usando 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

OutroPOSIX-apenasO método é retirar a substring "string", uma de cada vez do final do espaço do padrão, até que reste apenas uma (após a substring "test"). Então o que resta é trazer a substring "teste" à tona:

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

informação relacionada