Qual deve ser o resultado se a entrada for Here is a Here String? Ou I Hereby Dub Thee Sir Stringy?
ghoti
5
PARA SUA INFORMAÇÃO. Seu comando significa imprimir tudo entre a linha que possui a palavra Here e a linha que possui a palavra String - e não o que você deseja.
Obrigado! E se eu quisesse encontrar tudo entre "one is" e "String" em "Here is one is a String"? (sed -e 's / um é (*) Corda / \ 1 /.'?
user1190650
5
@ user1190650 Isso funcionaria se você também quiser ver o "Aqui está um". Você pode testá-lo: echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'. Se você quer apenas a parte entre "é" e "String", então você precisa fazer a regex corresponder toda a linha: sed -e 's/.*one is\(.*\)String.*/\1/'. Em sed, s/pattern/replacement/diga "substitua 'substituição' por 'padrão' em cada linha". Ele mudará apenas qualquer coisa que corresponda a "padrão"; portanto, se você quiser substituir a linha inteira, precisará fazer "padrão" corresponder à linha inteira.
Brian Campbell
9
Isso interrompe quando a entrada éHere is a String Here is a String
Jay D
1
Seria ótimo ver a solução para um caso: "Aqui está uma string blá blá Aqui está 1 uma string blá blá Aqui está 2 uma string blá blá blá" A saída deve pegar apenas a primeira substring entre Here e String "
Jay D
1
O @JayD sed não suporta correspondência não gananciosa; consulte esta pergunta para algumas alternativas recomendadas.
Brian Campbell
179
O GNU grep também pode suportar um olhar positivo e negativo positivo: para o seu caso, o comando seria:
echo "Here is a string"| grep -o -P '(?<=Here).*(?=string)'
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*(?=string)'# Greedy match
is a string, and Here is another
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*?(?=string)'# Non-greedy match (Notice the '?' after '*' in .*)
is a
is another
Observe que a -Popção do GNU grep não existe no grepincluído no * BSD ou nos que vêm com qualquer SVR4 (Solaris, etc). No FreeBSD, você pode instalar a devel/pcreporta que inclui pcregrep, que suporta o PCRE (e olha para frente / atrás). As versões anteriores do OSX usavam o GNU grep, mas no OSX Mavericks, -Pé derivado da versão do FreeBSD, que não inclui a opção.
ghoti
1
Olá, Como extraio apenas conteúdo distinto?
Durgesh Suthar
4
Isso não funciona porque se a sequência final "string" ocorrer mais de uma vez, ela receberá a última ocorrência, não a próxima ocorrência.
Buttle Butkus
6
No caso de Here is a string a string, ambas" is a " e " is a string a "são respostas válidas (ignore as aspas), conforme os requisitos da pergunta. Depende de você qual deles você deseja e a resposta pode ser diferente de acordo. De qualquer forma, para sua exigência, isso funcionará:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
Sua resposta é promissora. Uma questão embora. Como posso extraí-lo para a primeira String vista, se houver várias String na mesma linha? Obrigado
Mian Asbat Ahmad
@MianAsbatAhmad Você gostaria de tornar o *quantificador entre Heree Stringnão ganancioso (ou preguiçoso). No entanto, o tipo de regex usado pelo sed não suporta quantificadores preguiçosos ( ?imediatamente após .*) de acordo com esta pergunta do Stackoverflow. Geralmente, para implementar um quantificador preguiçoso, você apenas compara tudo, exceto o token que não deseja, mas nesse caso, não há apenas um único token, mas uma string inteira String.
por que esse método é tão lento? ao retirar uma página html grande usando esse método, leva 10 segundos.
Adam Johns
@AdamJohns, qual método? O PCRE? O PCRE é bastante complexo de analisar, mas 10 segundos parecem extremos. Se você estiver preocupado, recomendo que você faça uma pergunta, incluindo código de exemplo, e veja o que os especialistas dizem.
ghoti
Eu acho que foi muito lento para mim porque estava segurando uma fonte de arquivo html muito grande em uma variável. Quando escrevi o conteúdo do arquivo e o analisei, a velocidade aumentou drasticamente.
Adam Johns
22
Através do GNU awk,
$ echo "Here is a string"| awk -v FS="(Here|string)"'{print $2}'
is a
O grep com -P( perl-regexp ) suporta os parâmetros \K, o que ajuda a descartar os caracteres correspondidos anteriormente. No nosso caso, a string correspondida anteriormente foi Heredescartada da saída final.
$ echo "Here is a string"| grep -oP 'Here\K.*(?=string)'
is a
$ echo "Here is a string"| grep -oP 'Here\K(?:(?!string).)*'
is a
Se você deseja que a saída seja is a, tente o seguinte,
$ echo "Here is a string"| grep -oP 'Here\s*\K.*(?=\s+string)'
is a
$ echo "Here is a string"| grep -oP 'Here\s*\K(?:(?!\s+string).)*'
is a
Isso não funciona para :, echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'ele retorna apenas em is avez de deveria ser is a is a@Avinash Raj
alper
20
Se você possui um arquivo longo com muitas ocorrências de várias linhas, é útil imprimir primeiro as linhas numéricas:
Obrigado! Esta é a única solução que funcionou no meu caso (arquivo de texto com várias linhas, em vez de uma única sequência sem quebras de linha). Obviamente, para tê-lo sem numeração de linha, a -nopção in catdeve ser omitida.
Jeffrey Lebowski
... nesse caso, catpode ser totalmente omitido; sedsabe ler um arquivo ou entrada padrão.
tripleee
9
Isso pode funcionar para você (GNU sed):
sed '/Here/!d;s//&\n/;s/.*\n//;:a;/String/bb;$!{n;ba};:b;s//\n&/;P;D' file
Isso apresenta cada representação do texto entre dois marcadores (nesta instância Heree String) em uma nova linha e preserva as novas linhas dentro do texto.
Todas as soluções acima apresentam deficiências onde a última sequência de pesquisa é repetida em outro local da sequência. Eu achei melhor escrever uma função bash.
function str_str {local str
str="${1#*${2}}"
str="${str%%$3*}"
echo -n "$str"}# test it ...
mystr="this is a string"
str_str "$mystr""this "" string"
$ echo "Here is a String"| sed 's/.*Here//; s/String.*//'
is a
Também funciona
$ echo "Here is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
$ echo "Here is a StringHere is a StringHere is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
Isso remove as strings em vez de produzir algo no meio. Tente remover "Hello" com "is" no comando sed e ele exibirá "Hello a" #
Jonathan Jonathan
1
Problema. Minhas mensagens de correio de garras armazenadas são agrupadas da seguinte maneira e estou tentando extrair as linhas de assunto:
Subject:[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular
link in major cell growth pathway:Findings point to new potential
therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as
a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway
identified [Lysosomal amino acid transporter SLC38A9 signals arginine
sufficiency to mTORC1]]Message-ID:<20171019190902.18741771@VictoriasJourney.com>
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
sed ':a;N;$!ba;s/\n/ /g' corpus/01| grep -o -P '(?<=Subject: ).*(?=Message-ID:)'
que dá
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
Here is a Here String
? OuI Hereby Dub Thee Sir Stringy
?sed
FAQ comum é "como posso extrair texto entre linhas específicas"; isto é stackoverflow.com/questions/16643288/…Respostas:
fonte
echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'
. Se você quer apenas a parte entre "é" e "String", então você precisa fazer a regex corresponder toda a linha:sed -e 's/.*one is\(.*\)String.*/\1/'
. Em sed,s/pattern/replacement/
diga "substitua 'substituição' por 'padrão' em cada linha". Ele mudará apenas qualquer coisa que corresponda a "padrão"; portanto, se você quiser substituir a linha inteira, precisará fazer "padrão" corresponder à linha inteira.Here is a String Here is a String
O GNU grep também pode suportar um olhar positivo e negativo positivo: para o seu caso, o comando seria:
Se houver várias ocorrências de
Here
estring
, você poderá escolher se deseja corresponder da primeiraHere
e da últimastring
ou individualmente. Em termos de regex, é chamado de correspondência gananciosa (primeiro caso) ou correspondência não gananciosa (segundo caso)fonte
-P
opção do GNU grep não existe nogrep
incluído no * BSD ou nos que vêm com qualquer SVR4 (Solaris, etc). No FreeBSD, você pode instalar adevel/pcre
porta que incluipcregrep
, que suporta o PCRE (e olha para frente / atrás). As versões anteriores do OSX usavam o GNU grep, mas no OSX Mavericks,-P
é derivado da versão do FreeBSD, que não inclui a opção.Here is a string a string
, ambas" is a "
e" is a string a "
são respostas válidas (ignore as aspas), conforme os requisitos da pergunta. Depende de você qual deles você deseja e a resposta pode ser diferente de acordo. De qualquer forma, para sua exigência, isso funcionará:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
echo $'Here is \na string' | grep -zoP '(?<=Here)(?s).*(?=string)'
A resposta aceita não remove o texto que poderia ser antes
Here
ou depoisString
. Isso vai:A principal diferença é a adição de
.*
imediatamente antesHere
e depoisString
.fonte
*
quantificador entreHere
eString
não ganancioso (ou preguiçoso). No entanto, o tipo de regex usado pelo sed não suporta quantificadores preguiçosos (?
imediatamente após.*
) de acordo com esta pergunta do Stackoverflow. Geralmente, para implementar um quantificador preguiçoso, você apenas compara tudo, exceto o token que não deseja, mas nesse caso, não há apenas um único token, mas uma string inteiraString
..
não corresponde a quebras de linha. Se você quiser combinar quebras de linha, poderá substituí-lo.
por algo como[\s\s]
.Você pode retirar as strings apenas no Bash :
E se você tem um GNU grep que inclui PCRE , pode usar uma asserção de largura zero:
fonte
Através do GNU awk,
O grep com
-P
( perl-regexp ) suporta os parâmetros\K
, o que ajuda a descartar os caracteres correspondidos anteriormente. No nosso caso, a string correspondida anteriormente foiHere
descartada da saída final.Se você deseja que a saída seja
is a
, tente o seguinte,fonte
echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'
ele retorna apenas emis a
vez de deveria seris a is a
@Avinash RajSe você possui um arquivo longo com muitas ocorrências de várias linhas, é útil imprimir primeiro as linhas numéricas:
fonte
-n
opção incat
deve ser omitida.cat
pode ser totalmente omitido;sed
sabe ler um arquivo ou entrada padrão.Isso pode funcionar para você (GNU sed):
Isso apresenta cada representação do texto entre dois marcadores (nesta instância
Here
eString
) em uma nova linha e preserva as novas linhas dentro do texto.fonte
Todas as soluções acima apresentam deficiências onde a última sequência de pesquisa é repetida em outro local da sequência. Eu achei melhor escrever uma função bash.
fonte
Você pode usar dois comandos s
Também funciona
fonte
Para entender o
sed
comando, precisamos construí-lo passo a passo.Aqui está o seu texto original
Vamos tentar remover a
Here
string com as
opção ubstition emsed
Neste ponto, acredito que você seria capaz de remover
String
tambémMas este não é o resultado desejado.
Para combinar dois comandos sed, use a
-e
opçãoEspero que isto ajude
fonte
Você pode usar
\1
(consulte http://www.grymoire.com/Unix/Sed.html#uh-4 ):O conteúdo que está dentro dos colchetes será armazenado como
\1
.fonte
Problema. Minhas mensagens de correio de garras armazenadas são agrupadas da seguinte maneira e estou tentando extrair as linhas de assunto:
Por A2 neste tópico, como usar o sed / grep para extrair texto entre duas palavras? a primeira expressão, abaixo, "funciona", desde que o texto correspondente não contenha uma nova linha:
No entanto, apesar de tentar várias variantes (
.+?; /s; ...
), não consegui fazê-las funcionar:Solução 1.
Por extrair texto entre duas strings em linhas diferentes
que dá
Solução 2. *
Por Como posso substituir uma nova linha (\ n) usando sed?
substituirá as novas linhas por um espaço.
Encadeando isso com A2 em Como usar o sed / grep para extrair texto entre duas palavras? , Nós temos:
que dá
Essa variante remove espaços duplos:
dando
fonte