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 T
comando 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