com awk
way:
awk -F'*\*' 'NF>2{print $2}' infile
entrada de teste de amostra:
*wrd*
*woooord
**WRD
WORD**
woooooooooood*
**word**
a saída:
word
O comando grep
imprimirá uma linha quando a linha contiver uma string que corresponda a uma expressão, o que não é útil para pesquisar conteúdo específico.
Por exemplo, eu tenho arquivos de vocabulário com formatação
**word**
1. Definition:
2. Usage
3. Others
Gostaria de recuperar todas as palavras para criar uma lista de palavras nos arquivos
grep '\*\*[^*]*\*\*'
Retorna a maior parte do conteúdo.
Como usar grep
para capturar apenas o word
?
com awk
way:
awk -F'*\*' 'NF>2{print $2}' infile
entrada de teste de amostra:
*wrd*
*woooord
**WRD
WORD**
woooooooooood*
**word**
a saída:
word
Assim, por enquanto, usando perl regex ( -P
) :
grep -oP '^\s*\*\*\K[^*]+(?=\*\*)' file
word
Assim como para palavras:
grep -oP '^\s*\d+\.\s*\K\w+' file
Definition
Usage
Others
Existem várias ferramentas disponíveis que podem ser usadas para extrair palavras; aqui está uma versão implementada no sed:
sed '/^\*\*/!d' <your_file
Este comando corresponderá a todas as linhas do seu arquivo que começam com **
e imprimem. As outras linhas serão excluídas da saída. Se você também quiser remover as estrelas, pode estender o comando para isso:
sed '/^\*\*/!d;s/\*//g' <your_file
Este comando, além disso, removerá todos os caracteres *
da linha antes de ser impressa.
Esta é uma daquelas perguntas em que é útil ter um arquivo de entrada de teste e exemplos de saída desejada.
Aqui está um arquivo de entrada de teste que eu copiei da Internet e modifiquei para encapsular palavras de busca em **
pairs:
$ cat ~/Downloads/wordlist.txt
**Schadenfreude**
This is a German word, although used in English too, which is used to mean ‘malicious enjoyment of the misfortunes of others’. It comes from the joining of the words schaden meaning ‘harm’ and freude meaning ‘joy’.
**Waldeinsamkeit**
Ever found yourself wandering alone through a forest and wanting to express the emotion brought about by that wander? Look no further! In German, Waldeinsamkeit means ‘woodland solitude’.
**L’esprit de l’escalier**
We all know the feeling of walking away from an argument and instantly thinking of the ideal comeback, or leaving a conversation and remembering the perfect contribution to a no-longer relevant subject. In French, l’esprit de l’escalier is the term used to refer to that irritating feeling. It literally translates as ‘the spirit of the staircase’, more commonly known as ‘staircase wit’. It comes from the idea of thinking of a response as you’re leaving somebody’s house, via their staircase.
**Schlimazel**
The Mr Men series of books by Roger Hargreaves is a staple of many a British child’s bookshelves, and there is a word which could have been created for the character Mr Bump. Like Mr Bump, a Schlimazel is ‘a consistently unlucky, accident-prone person, a born loser’. It is a Yiddish word, coming from the Middle High German word slim meaning ‘crooked’ and the Hebrew mazzāl meaning ‘luck’.
**Depaysement**
Ever go on holiday, only to experience a strange sensation of disorientation at the change of scenery? Dépaysement is a French word which refers to that feeling of disorientation that specifically arises when you are not in your home country.
**Duende**
This Spanish term implies something magical or enchanting. It originally referred to a supernatural being or spirit similar to an imp or pixie (and is occasionally borrowed in that sense into English with reference to Spanish and Latin American folklore). Now, it has adapted to refer to the spirit of art or the power that a song or piece of art has to deeply move a person.
**Torschlusspanik**
Are you getting older? Scared of being left behind or ‘left on the shelf’? This British idiom has its own word in German: Torschlusspanik, which literally translates as ‘panic at the shutting of a gate’, is used frequently in a general sense meaning ‘last –minute panic’, of the type you might experience before a deadline.
*Do*Not*Return*these four star lines
*word***
***word*
word**
grep
Usando grep
, é bastante simples obter uma lista de palavras:
$ grep -E -o '\*\*[^*]{,20}\*\*' ~/Downloads/wordlist.txt
**Schadenfreude**
**Waldeinsamkeit**
**L’esprit de l’escalier**
**Schlimazel**
**Depaysement**
**Duende**
**Torschlusspanik**
Se você quiser remover o **
que contém as palavras, adicione um canal a sed
:
$ grep -E -o '\*\*[^*]{,20}\*\*' ~/Downloads/wordlist.txt | sed 's/*//g'
Schadenfreude
Waldeinsamkeit
L’esprit de l’escalier
Schlimazel
Depaysement
Duende
Torschlusspanik
Se você deseja salvar sua saída grep
e sed
use o redirecionamento de arquivo >
command:
$ grep -E -o '\*\*[^*]{,20}\*\*' ~/Downloads/wordlist.txt | sed 's/*//g' > ~/Downloads/wordlist-index.txt
$ cat ~/Downloads/wordlist-index.txt
Schadenfreude
Waldeinsamkeit
L’esprit de l’escalier
Schlimazel
Depaysement
Duende
Torschlusspanik
Nota resposta original postada ontem reforçada com novo post hoje de muru em um separado Q & A: Use um quantificador especificado no grep para recuperar o vocabulário satisfeito
Se você não se importar em usar ferramentas adicionais, uma solução muito simples seria postar o filtro grep
output com tr
para excluir todas as ocorrências do caractere *
:
grep -x '\*\*[^*]*\*\*' | tr -d '*'
Eu também recomendo que você use o -x
flag do GNU grep como acima para combinar apenas linhas inteiras para não capturar acidentalmente **word**
aparecendo rodeado por outro texto na mesma linha. Isso também pode acelerar o processo de correspondência de padrões, já que agora ele pode descartar muitas correspondências possíveis.
sed
alternativa Você também pode aproveitar o flag p
do sed para corresponder, substituir e imprimir como um único comando:
sed -nre 's/^\*\*([^*]*)\*\*$//p'
Seu caso particular é extrair texto entre dois padrões em uma linha / string. Isso foi abordado na pergunta de 2012 Como usar o sed / grep para extrair texto entre duas palavras? . Particularmente, como anishsane mencionado, você pode usar padrões de look-ahead e look-back com o sinalizador Perl-regex -P
. No seu caso particular, a solução seria
grep -o -P '(?<=\*\*).*(?=\*\*)' input.txt
No entanto, como ghoti mencionado, -P
é específico para o GNU grep
. Tenha isso em mente se você estiver portando seus scripts / comandos entre diferentes sistemas * nix.
Em vez de tentar usar o regex Perl, vamos usar o próprio Perl:
$ perl -a -F\*\* -lane 'print $F[1] if /\*\*/' input.txt
word
Isso tem duas vantagens. Um, especifica o delimitador para "campos", o que significa que podemos lidar com itens individuais separados por **
. Em segundo lugar, sintaticamente, isso é apenas um pouco menos confuso do que o padrão look-ahead / back.
Claro, existem outras maneiras de fazer isso, e uma delas é Python. O script do Python 2.7 seria:
#!/usr/bin/env python
from __future__ import print_function
import sys
for f in sys.argv[1:]:
with open(f) as fd:
for line in fd:
if line.startswith('**'):
print(line.split('*')[2])
Você também pode criar uma linha única e aproveitar o redirecionamento de stdin:
python -c 'import re,sys; print "\n".join([ l.split("**")[1] for l in sys.stdin if "**" in l ])' < input.txt
Outras pessoas que preferem regex, podem usar o módulo re
.
python -c 'import re,sys; print "\n".join([ re.split("\*\*",l)[1] for l in sys.stdin if "**" in l ])' < input.txt