excluindo um caractere antes de um determinado caractere em sed [closed]

0

Eu tenho esse arquivo que simplesmente imprime uma linha. Estou trabalhando na manipulação desta linha com diferentes comandos sed.

apple orange.5678 dog cat 009 you

Eu estou querendo pegar 'orange.5678' e incluir 'you' e ignorar todo o resto. Eu quero que pareça abaixo

orange.5678 you

Não sei por onde começar e como excluir tudo, exceto "orange.5678" e "you". Qualquer ajuda seria ótima!

    
por Nack 21.01.2017 / 04:04

4 respostas

5
$ sed -r 's/.* ([^ ]+\.[^ ]+).* ([^ ]+)$/ /' orange
orange.5678 you

Explicação

  • -r usa expressões regulares estendidas
  • s/old/new replace old com new
  • .* qualquer número de caracteres
  • (some characters) save some characters para referência posterior na substituição
  • [^ ]+ alguns caracteres que não são um espaço
  • \. literal dot
  • $ fim da linha
  • backreference para o padrão salvo

so s/.* ([^ ]+\.[^ ]+).* ([^ ]+)$/ / significa, corresponde qualquer coisa na linha até um espaço que precede alguns caracteres não espaciais até . e depois alguns caracteres não espaciais após (salvando esses caracteres de cada lado do . ), em seguida, combine todos os caracteres e salve o último conjunto de caracteres não espaciais na linha e substitua a correspondência inteira pelos dois padrões salvos separados por um espaço

    
por 21.01.2017 / 06:13
4

Abordagem mais simples:

awk '{print $2, $6}' file.txt

Se o seu caso de uso real é mais complexo do que a sua pergunta indica, e você precisa de lógica adicional (por exemplo, se não é sempre o segundo e o sexto campos que você precisa), edite sua pergunta para esclarecer.

    
por 21.01.2017 / 06:21
1

Deve-se olhar para outra resposta de @Zanna. Muito elegante e mostra o poder das expressões regulares.

Experimente esta expressão com gawk . O awk simples não funciona com o agrupamento.

^(?:\w+\s){0,}(\w+\.\w+)(?:\s\w+){0,}\s(\w+)$

Funcionou para acompanhar as variações

apple orange.5678 dog cat 009 you
apple apple grape.9991 pig cat piegon owl
grape.9991 pig cat piegon owl

Aqui está a descrição da expressão.

/
^(?:\w+\s){0,}(\w+\.\w+)(?:\s\w+){0,}\s(\w+)$
/
g
^ asserts position at start of the string

Non-capturing group (?:\w+\s){0,}
{0,} Quantifier — Matches between zero and unlimited times, as many times as possible, giving back as needed (greedy)
\w+ matches any word character (equal to [a-zA-Z0-9_])
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
\s matches any whitespace character (equal to [\r\n\t\f\v ])

1st Capturing Group (\w+\.\w+)
\w+ matches any word character (equal to [a-zA-Z0-9_])
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
\. matches the character . literally (case sensitive)
\w+ matches any word character (equal to [a-zA-Z0-9_])
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)

Non-capturing group (?:\s\w+){0,}
{0,} Quantifier — Matches between zero and unlimited times, as many times as possible, giving back as needed (greedy)
\s matches any whitespace character (equal to [\r\n\t\f\v ])
\w+ matches any word character (equal to [a-zA-Z0-9_])
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
\s matches any whitespace character (equal to [\r\n\t\f\v ])

2nd Capturing Group (\w+)
\w+ matches any word character (equal to [a-zA-Z0-9_])
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
$ asserts position at the end of the string, or before the line terminator right at the end of the string (if any)
    
por 21.01.2017 / 04:28
0

Se tiver que ser sed com regex, a resposta acima cobrirá você. Se você está aberto a alternativas:

gv@debian: $ read -r a b c d e f<<<"apple orange.5678 dog cat 009 you" && echo "$b $f" 
orange.5678 you

Se esta for uma linha em um arquivo, substitua <<<"...." por <file

Este método para trabalhar requer IFS = espaço padrão. Se em doube, aplique IFS=" " no começo.

    
por 21.01.2017 / 14:54