Como posso "mesclar" padrões em uma única linha?


10

Estou fazendo grep e sed e recebo 2 linhas de um arquivo no qual estou interessado. Como posso obter essas linhas em uma única linha que termina com o novo caractere de linha?
Agora estou recebendo:

pattern1  
pattern2  

Eu gostaria de receber pattern1 pattern2 \n


1
Você pode compartilhar mais dados de amostra?
slm

Use printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'
Valentin Bajrami

Colar é a ferramenta para o trabalho, se você pretende mesclar várias linhas de saída em uma.
slm

alguma ferramenta específica? Como você planeja fazer isso?
Braiam 23/08/14

Respostas:


7

paste:

{...pipeline...} | paste -d " " - -

Isso diz: "leia uma linha do stdin (o primeiro -), leia outra linha do stdin (o segundo -) e junte-os a um espaço"


uma técnica específica do bash:

$ x=$(grep -o pattern. test.txt)
$ echo "$x"
pattern1
pattern2
$ mapfile -t <<< "$x"
$ echo "${MAPFILE[*]}"
pattern1 pattern2

ref: http://www.gnu.org/software/bash/manual/bashref.html#index-mapfile


O que é - -? O comando é assim?
Jim

@ Jim - sim, está correto. Eles estão dizendo pastecomo você deseja que ele processe a entrada. 2 de cada vez. Adicione mais para fazer 3 de cada vez. seq 10 | paste -d " " - - .
slm

6

Vou colocar três versões diferentes métodos seguidos

AWK

printf %s\\n pattern1 pattern2 | awk -vRS="\n" -vORS=" " '1; END {print RS}'

SED

printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'

TR

printf %s\\n pattern1 pattern2 | tr '\n' ' '; echo

E há muito mais.


A trsolução vai engolir a nova linha terminando, assim você pode querer adicionar ; echoa esse
Glenn Jackman

@glennjackman ah certo! Obrigado pela dica. Você é livre para modificar a resposta. Eu perdi esse pedaço!
Valentin Bajrami

2

você pode fazê-lo usando o shell script ou na linha de comando, basta colocar a saída do comando em uma variável e depois echo:

# x=$(grep -e "pattern1\|pattern2" test)
# printf '%s\n' "$x"
pattern1 pattern2

sem aspas, a variável também está sujeita à expansão do nome do arquivo; portanto, se você tiver algum caractere glob (como *ou ?) no resultado, os valores poderão mudar.
precisa saber é o seguinte

@glennjackman, obrigado por mencionar isso, como podemos corrigir isso?
Nidal

@Networker por não usar acentos graves, mas $()em vez .. e usando printfprintf '%s\n' "$x"
Valentin Bajrami

Espero que printf '%s\n' "$x"NÃO remova a nova linha "interna".
precisa saber é o seguinte

2

Com sed, você pode fazer isso:

<your previous commands> | sed '{N; s/\n/ /}'
  • N;manda sedadicionar a próxima linha ao espaço do padrão, agora agora sedestá trabalhando com as duas linhas.
  • s/\n/ / substitui o caractere de nova linha por um espaço, "mesclando" as duas linhas.

2

Uma maneira simples, canalize a saída para xargs:

$ echo -e 'a\nb' | xargs
a b

Isso funciona apenas com saída pequena, porque é limitado pelo máximo de caracteres por linha de comando. O maior valor depende do sistema, você pode obter esse valor usando getconf ARG_MAX.


1
( set -f; IFS='
'; printf '%s %s\n' $(grepcmd <input)
) >output

O IFS ficará feliz em comê-lo, se quiser.


-1

envolva seu sed / grep em backticks

quando seu comando original era:

grep -i 'foo' mylog.log | sed 's/bar/baz/gi'

seu novo comando seria:

`grep -i 'foo' mylog.log | sed 's/bar/baz/gi'`

Não coloca os espaços entre as linhas, mas você sempre pode prender em outro tubo de sed:

 | sed 's/$/ /'

1
Oh não. Isso executará a saída do comando sed.
Glenn Jackman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.