Explicação de linha por linha e pipe-a-pipe:
#!/bin/bash
Este é um chamado shebang - basicamente diz para executar este script com o programa /bin/bash
.
cat $1
$1
é o primeiro argumento de script. cat $1
vai gerar o conteúdo do arquivo fornecido como primeiro argumento de script para stdout. No entanto, como há um pipe depois disso, o stdout será canalizado para stdin do próximo comando no pipeline, grep
neste caso.
grep "^$2[0-9]*.*$3 +[0-9]*\ [0-9]*\ [0-9]*"
Isto irá ler o stdin (que cat $1
output acima). Você pode ler mais sobre grep, por exemplo, aqui:
O item acima filtrará as linhas fornecidas a ele por regex. O regex:
^$2[0-9]*.*$3 +[0-9]*\ [0-9]*\ [0-9]*
basicamente diz que queremos linhas que:
- Comece com o segundo argumento de script (
$2
acima), - Em seguida, tenha zero ou mais dígitos (
[0-9]*
) - Seguido por zero ou mais ocorrências de (quase) qualquer caractere
- Seguido pelo terceiro argumento de script (
$3
) - Seguido por dois ou mais espaços (
+
- observe que há dois espaços aqui) - Seguido de zero ou mais dígitos (
[0-9]*
) - seguido por um espaço (
\
) - Seguido de zero ou mais dígitos (
[0-9]*
) - seguido por um espaço (
\
) - Seguido de zero ou mais dígitos (
[0-9]*
)
Todas as linhas que correspondem ao acima serão emitidas para stdout. Novamente, o stdout é canalizado para o stdin do próximo comando, sed
neste caso.
sed "s/\([0-9]*\)\t\(.*\)\t\(.\).*\t\(.*\)\t\(.\).*\t+[0-9]*\ [0-9]*\
\([0-9]*\)/ /"
Você pode ler sobre sed
mais, por exemplo, aqui:
O acima diz basicamente, para cada linha:
- Substituir (
s/
) - (A) Isto:
\([0-9]*\)\t\(.*\)\t\(.\).*\t\(.*\)\t\(.\).*\t+[0-9]*\ [0-9]*\([0-9]*\)
- (B) Com isso:
A parte marcada com (A) acima é o regexp novamente, semelhante ao que o grep usou. O que diz é um pouco mais regular. Note que tem uma estrutura ao longo das linhas X\tY\tZ\t...
. O que isso essencialmente diz para sed
é - corresponde a uma linha que possui caracteres de tabulação (é isso que \t
significa) e algumas coisas ( X
, Y
, Z
) entre elas. Essas coisas acima podem ser agrupadas de duas maneiras:
- Expressões como
\([0-9]*\)
são chamadas de grupos de captura de expressão regular. Eles são basicamente delimitados por parênteses, exceto quesed
é um pouco mais antigo do que a maneira usual de fazer em regexps hoje. Por exemplo. Se você usasse uma ferramenta de regex como o link , em vez disso, colocaria([0-9]*)
.sed
precisa que estes sejam escapados para indicar grupos - caso contrário, seria necessário que correspondesse aos parênteses reais. Ele pode ser instruído a fazer o inverso fornecendo a opção de linha de comando-r
- Expressões fora dos parênteses de escape (por exemplo, a parte
\t+[0-9]*
)
A captura de grupos é o que permite que sed
faça o que você está pedindo. Observe a parte (B) do comando sed
. Diz isso:
Esta é realmente uma boa maneira de dizer - substitua o que combinei nesta linha o quinto grupo de captura, depois o primeiro grupo, depois um espaço, depois um segundo grupo, etc.
Para deixar mais claro, aqui está um exemplo de comando para você tentar:
echo abc|sed 's/\(.\)\(.\)\(.\)//'
ou se você quiser em um formato de regex estendido que seja mais fácil de ler:
echo abc|sed -r 's/(.)(.)(.)//'
Execute-o e veja o que isso gera - observando que o eco gera três caracteres na linha e que para sed
part .
corresponde (quase) qualquer caractere, deve ficar claro o que e como isso se aplica à sua situação. Eu sugiro que você jogue com alguns exemplos de substituição de sed na Net - essa deve ser a melhor maneira de esclarecer as coisas.
Espero que isso ajude.