2 coisas:
- Conforme declarado pelo @Rory, você precisa da
-o
opção, para que apenas a correspondência seja impressa (em vez da linha inteira)
- Além disso, você precisa da
-P
opção de usar expressões regulares do Perl, que incluem elementos úteis como Olhar para a frente (?= )
e Olhar para trás (?<= )
, que procuram por peças, mas na verdade não coincidem e as imprimem.
Se você deseja que apenas a parte dentro da parêntese seja correspondida:
grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt
se o arquivo contiver a picada /(a)5667/
, o grep imprimirá 'a', porque:
/(
são encontrados por \/\(
, mas, como estão olhando para trás (?<= )
, não são relatados
a
é correspondido por \w
e, portanto, é impresso (por causa de -o
)
)5667/
são encontrados b < \).+\/
, mas como eles estão olhando para o futuro, (?= )
eles não são relatados
sed
para fazer isso?fonte
Se você deseja apenas o que está entre parênteses, precisa de algo que suporte a captura de subconjuntos (grupos de captura nomeados ou numerados). Eu não acho que grep ou egrep possam fazer isso, perl e sed can. Por exemplo, com perl:
Se um arquivo chamado foo tiver uma linha, é a seguinte:
E você faz:
A letra a é retornada. Isso pode não ser o que você deseja. Se você nos dizer com o que está tentando corresponder, poderá obter melhor ajuda. $ 1 é o que foi capturado no primeiro conjunto de parênteses. $ 2 seria o segundo conjunto etc.
fonte
Como você marcou sua pergunta como bash , além do shell , há outra solução ao lado do grep :
O Bash possui seu próprio mecanismo de expressão regular desde a versão 3.0, usando o
=~
operador, assim como o Perl.agora, com o seguinte código:
bash
e não apenassh
para obter todas as extensões$BASH_REMATCH
dará a string inteira conforme a expressão regular inteira, então<Lane>8</Lane>
${BASH_REMATCH[1]}
dará a parte correspondente ao 1º grupo, portanto, apenas8
fonte
>
símbolo para propósitos totalmente diferentes), conforme divulgada pelo software de alinhamento rápido em grande escala SANSparallel . É claro que ambos os formatos são espalhados sem entrelaçar. Portanto, é impossível jogar alguma biblioteca XML padrão nisso. E eu estou usando o regex Bash neste ponto do código, porque eu só preciso extrair alguns dados, e o 2 regex faz o trabalho muito melhor para mim do que escrever um analisador dedicado para essa bagunça. #LifeInBioinformaticsSupondo que o arquivo contenha:
E você deseja o (s) caractere (s) entre
>
e</
, você pode usar:grep
grep -oP '.*\K(?<=>)\w+(?=<\/)' file
sed
sed -nE 's:^.*>(\w+)</.*$:\1:p' file
awk
awk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
perl
perl -nle 'print $1 if />(\w+)<\//' file
Todos imprimirão uma string "xyz".
Se você deseja capturar os dígitos desta linha:
grep
grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sed
sed -E 's:^.*>([0-9]+)</.*$:\1:' file
awk
awk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
perl
perl -nle 'print $1 if />([0-9]+)<\//' file
fonte
echo 'Text-<here>1234</text>-ends' | sed -E 's|.*>([[:digit:]]+)<.*|\1|'
. Em alguns casos (por exemplo,[0-9]
vs.[[:digit:]]
), eles não ajudam a legibilidade; em outros, acho que ajudam (por exemplo,[ \t\n\r\f\v]
vs.[:space:]
).Isso realizará o que você está solicitando, mas não acho que seja o que você realmente deseja. Coloquei a
.*
parte da frente da regex para comer qualquer coisa antes da partida, mas essa é uma operação gananciosa, portanto, isso só corresponde ao penúltimo\w
caractere na string.Note que você precisa escapar dos parênteses e dos
+
.fonte