O que a declaração Bash faz

1

Você pode me explicar o que a declaração abaixo faz?

grep 'date +%Y-%m-%d --date='1 day ago'' /path/to/file/FILE_PREFIX_\'date +%Y%m%d --date='1 day ago''.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'
    
por Nicholas Namacha 31.07.2015 / 09:07

2 respostas

2

Suponha que tenhamos este arquivo:

$ cat path/to/file/FILE_PREFIX_20150730.dsv
2015-07-29|0100
2015-07-30|0200
2015-07-30|0300
2015-07-31|0400

Agora observe o que seu comando (ligeiramente fixo) faz:

$ grep 'date +%Y-%m-%d --date='1 day ago'' path/to/file/FILE_PREFIX_'date +%Y%m%d --date='1 day ago''.dsv  | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'
27200
27300

Em suma, ele olha para um arquivo cujo nome é baseado na data de ontem, path/to/file/FILE_PREFIX_20150730.dsv . Ele procura por qualquer linha nesse arquivo que mencione a data de ontem no formulário 2015-07-30 . Em seguida, elimina qualquer linha que contenha também os caracteres ERROR . As linhas restantes são divididas em campos com base no caractere | . O segundo campo da linha é extraído. Se esse segundo campo começar com zero, o zero será substituído por 27 .

    
por 31.07.2015 / 09:43
0

Para começar, o que você dá não é uma afirmação. É um monte de comandos encadeados através de Pipes e Comando de substituição .

grep 'date +%Y-%m-%d --date='1 day ago'' /path/to/file/FILE_PREFIX_\'date +%Y%m%d --date='1 day ago''.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

Vamos separá-los um por um.

Substituição de Comando

  • date +%Y-%m-%d --date='1 day ago' aparece duas vezes e mostra a data de ontem no formato YYYY-mm-dd (por exemplo, 2015-07-31)
    • A segunda chamada (a que está no nome do caminho) ajusta o formato para YYYYmmdd
    • Colocá-lo em backticks faz com que seja uma substituição de comandos . Isso é o mesmo que você alcançaria digitando $(date +%Y-%m-%d --date='1 day ago') apenas que o último formulário (e mais recente) permite o aninhamento e é menos complicado em relação ao escape.

O efeito de Substituição de Comando em sua linha de comando é semelhante a atribuir

YESTERDAY1=$(date +%Y-%m-%d --date='1 day ago')
YESTERDAY2=$(date +%Y%m%d --date='1 day ago')

e depois reescrevendo a linha de comando assim

grep $YESTERDAY1 /path/to/file/FILE_PREFIX_$YESTERDAY2.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

As partes individuais encadeadas por tubos

  • grep $YESTERDAY1 /path/to/file/FILE_PREFIX_$YESTERDAY2.dsv greps para o valor da data de ontem no arquivo /path/to/file/FILE_PREFIX_$YESTERDAY2.dsv e sai para stdout (consulte Standard Streams )
  • grep -v 'ERROR' greps para tudo outro que linhas contendo ERROR . Ele faz isso na entrada de stdin e também grava em stdout .
  • cut -d "|" -f 2 assume que a linha de entrada (de stdin ) é delimitada por caracteres de canal ( -d "|" , observe como o caractere de canal está em uma string aqui!) e escolhe o segundo campo ( -f 2 ) e grava isso em stdout .
  • sed 's/^0/27/' substitui ( s/.../.../ ) todas as strings de stdin (lembre-se, segundo campo da entrada original) iniciando ( ^ ) com 0 por 27 e grava-as em stdout .

Tubulação

Agora, os caracteres de canal que aparecem fora de uma string, ou seja, todos, exceto o único em cut -d "|" -f 2 encadearam o stdout do comando anterior para stdin do comando a seguir.

Dessa forma, a saída do primeiro grep que lê o arquivo, vai para o segundo grep , o qual

Isso segue o princípio de filosofia do Unix "Faça uma coisa e faça bem" .

Colocando tudo junto

Na minha explicação, usei a variável YESTERDAY1 e YESTERDAY2 introduzida na seção Substituição de Comando. Agora você deve ser capaz de entender isso.

Uma coisa, no entanto. Eu duvido que isso aconteça, mas em um sistema muito lento em torno da meia-noite, o tempo entre a execução dessas duas substituições de comandos pode ser grande o suficiente para gerar valores diferentes para o nome do arquivo e o valor para o qual grep .

A propósito

Se você quer ser realmente sofisticado e evitar o problema de que o valor de ontem poderia ser diferente, você pode usar Expansão de Parâmetro ( ${parameter/pattern/string} ) como tal. Primeiro, coloque a data em uma variável por meio de Substituição de comando :

YESTERDAY=$(date +%Y-%m-%d --date='1 day ago')

e, em seguida, use a Expansão do Parâmetro para remover os traços de uma vez da instância da variável da seguinte forma:

grep $YESTERDAY /path/to/file/FILE_PREFIX_${YESTERDAY//-}.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

Dessa forma, você recupera o valor de data apenas uma vez e evita a chance (ainda que pequena) de obter datas diferentes.

Sugestão de leitura

por 31.07.2015 / 10:46

Tags