Usando o pipe STDOUT como uma variável?

2

Bastante novo para Bash, sobre uma semana cansativa. Eu amo isso até agora e realmente gosto de longos tubos de encadeamento. O que eu estou percebendo é que eu tenho que quebrar o pipe se eu precisar usar o STDOUT como uma variável.

Veja um exemplo:

echo -e 'Going to the movies can be fun.
When a dog found a cat a trouble began.
Do not text while driving please.' > example

Suponha que eu queira substituir todos os "A" por "THE" na segunda linha. Aqui está como eu faço atualmente.

cat example | head -2 | tail -1 | sed 's/ a / the /g'

Veja como eu gostaria de fazer isso

# None of these work
cat example | head -2 | tail -1 | ${xargs//a /the } 
cat example | head -2 | tail -1 | ${cat//a /the }
cat example | head -2 | tail -1 | ${$0//a /the }
cat example | head -2 | tail -1 | ${//a /the }

Neste momento eu teria que criar uma variável e usar a manipulação de string do bash.

middle=$(cat example | head -2 | tail -1)
echo ${middle//a /the }

Eu percebo que para este exemplo você pode usar muitas ferramentas

cat example | awk 'gsub(/ a/," the");'

O que estou realmente tentando descobrir é se existe alguma maneira de usar o pipe STDOUT como uma variável.

    
por Proximo 12.08.2018 / 09:28

2 respostas

2

Como faço para substituir um com o na segunda linha e, em seguida, continuar o pipeline?

Primeiro, corrija o sed para corresponder a todos os a s, evento como início e fim.

sed -r -e 's/(^| )a($| )/the/g'

Em seguida, faça corresponder apenas na linha 2

sed -r -e '2 s/(^| )a($| )/the/g'

Agora você pode fazer

echo -e 'Going to the movies can be fun.
When a dog found a cat a trouble began.
Do not text while driving please.' | sed -r -e '2 s/(^| )a($| )/the/g' | less

Outra solução

Primeiro, solte o cat

cat está abrindo um arquivo e passando para sua saída, que é então canalizada para o próximo comando. Podemos obter o shell para abrir um arquivo e direcioná-lo para a entrada do próximo comando (agora primeiro), usando o redirecionamento de entrada ( < ). Podemos escrever isso como command args <input-file ou <input-file command args . Não importa onde dentro do comando nós colocamos o <input-file . Eu coloquei o redirecionamento primeiro, para que a linha do tubo possa ser lida da esquerda para a direita.

< example head -2 | tail -1 | sed 's/ a / the /g'

Alternativa (que faz exatamente a mesma coisa):

head -2 <example | tail -1 | sed 's/ a / the /g'

eles fazem o mesmo que o seguinte, mas com um processo a menos.

cat example | head -2 | tail -1 | sed 's/ a / the /g'

Próximo encapsulado: aqui colocamos parênteses em torno de 3 comandos, podemos então canalizar a saída de todos os 3 para outro comando (aqui eu uso menos).

{  
  < example head -1
  < example head -2 | tail -1 | sed 's/ a / the /g'
  < example tail -1
} | less
    
por 12.08.2018 / 13:10
0

A substituição de comandos é o caminho a percorrer (como você faz com $middle ), mas a IMHO apenas passando por sed nessas situações é mais fácil.

Dito isto: Eu sei que você está apenas aprendendo, mas combinar head , tail e sed dificilmente é necessário. Seu exemplo pode ser expresso em sed puro como

sed -n '2s/ a / the /gp' example
  • -n suprime a saída por padrão
  • 2 corresponde à segunda linha
  • s/ a / the /g substitui todas as ocorrências ("g" lobal) de a .
  • p imprime o resultado
por 12.08.2018 / 09:42