torrado no OS X - extrai todo o texto entre colchetes

3

Dado este fluxo:

[foo] 123 [bar]
[gar] dsa [har] 345
[uf] 88 [gc] 43 [br]

Eu quero processar isso com sed (ou qualquer outra coisa) para que a saída seja:

foo bar
gar har
uf gc br

Eu tentei cat myfile | sed -e 's/^.*\[//;s/\].*$//'

Mas isso me dá apenas a última instância.

Minha entrada real é algo como:

53f42d4 [the contacts are duplicated] Adding support in picking email verified users [https://trello.com/c/663]
3c454b0 [the contacts are duplicated] splitting contact by phone numbers and emails and changing contact model to contain only 1 email [https://trello.com/c/663]
0e63e5b [we should not let a user confirm his email if we have a user with this confirmed email already] better doc [https://trello.com/c/643]
02671b7 [we should not let a user confirm his email if we have a user with this confirmed email already] preventing updating email if already in used by other user [https://trello.com/c/643]

Então, eu gostaria de obter a primeira linha:

the contacts are duplicated https://trello.com/c/663
    
por YardenST 18.10.2018 / 17:12

5 respostas

3

o awk funciona bem também para isso: usando [ ou ] como o separador de campo, imprima todos os campos números pares :

awk -F '[][]' '{for (i=2; i<=NF; i+=2) {printf "%s ", $i}; print ""}' file

Com sed, eu escreveria

sed -E 's/(^|\])[^[]*($|\[)/ /g' file
    
por 18.10.2018 / 18:23
4

Isto irá corresponder qualquer coisa dentro do primeiro colchete (abertura) ao primeiro colchete (fechamento) que se segue, várias vezes.

$ sed 's/[^[]*\[\([^]]*\)\][^[]*/ /g' file
foo bar
gar har
uf gc br

Descrição:

sed '                      # start a sed script
        s/                 # start a substitute command
        [^[]*              # match all leading characters (except [)
        \[                 # match an explicit [
        \([^]]*\)          # capture text inside brackets.
        \]                 # match the closing ]
        [^[]*              # match trailing text (if any).
        / /              # replace everything matched by the captured text.
        g                  # repeat for all the line.
       ' file              # close script. Apply to file.

Isso adiciona um espaço à direita por correspondência. Se isso precisar ser removido, adicione uma remoção no final:

sed -e 's/[^[]*\[\([^]]*\)\][^[]*/ /g' -e 's/ $//' file

Se você tiver o grep do GNU, isso pode ajudar (uma linha por captura).

grep -Po '\[\K[^]]*(?=])'

E, se o acima não funcionar, o awk também poderá:

awk '{print gensub(/\[([^]]*)\][^[]*/,"\1 ","g")}' file
    
por 18.10.2018 / 18:21
3

Uma maneira idiomática de fazer isso é usar as asserções, consulte, por exemplo. link , mas estes não são suportados no sed, apenas em processadores de expressão regular compatíveis com PCRE.

Como o Perl deve estar disponível no macOS por padrão, talvez essa seja uma alternativa viável.

Usando o Perl, você poderia dizer

perl -pe 's/.+?(?<=\[)(.+?)(?=\]).+?/$1 /g'

(observe que isso adiciona um espaço no final da linha)

Para uma explicação sobre o padrão, consulte o link .

    
por 18.10.2018 / 18:26
2

Isso parece funcionar:

$ sed -E 's/ [^[][a-zA-Z0-9][^]]/ /g;s/ +/ /g' input | tr -d '[]'
foo bar
gar har
uf gc br
    
por 18.10.2018 / 17:23
1

Uso:

sed -n '/\[/ { s-[^[]*--; s-\[\([^]]*\)\][^[]*- -g; s- --p }'

O algoritmo é:

  • Ignorar linhas que não contêm colchetes.
  • Remover o texto antes do primeiro parênteses.
  • Substitua pares de colchetes por espaços, deixando o texto dentro dos colchetes.
  • Remove o espaço inicial, deixando apenas espaços entre eles.
por 18.10.2018 / 18:04