Pergunta

Existe algum comando bash que lhe permitirá obter a linha enésima de STDOUT?

Ou seja, algo que levaria este

$ ls -l
-rw-r--r--@ 1 root  wheel my.txt
-rw-r--r--@ 1 root  wheel files.txt
-rw-r--r--@ 1 root  wheel here.txt

e fazer algo como

$ ls -l | magic-command 2
-rw-r--r--@ 1 root  wheel files.txt

Sei que isso seria má prática ao escrever roteiros destinados a ser reutilizados, mas quando se trabalha com o dia-a-dia shell que seria útil para mim ser capaz de filtrar meu STDOUT de tal maneira.

Eu também percebo isso seria comando semi-trivial para escrever (tampão STDOUT, retornar uma linha específica), mas eu quero saber se há alguma padrão comando shell para fazer este que estaria disponível sem me deixar cair um script no lugar.

Foi útil?

Solução

Usando sed, apenas para variedade:

ls -l | sed -n 2p

Com esta alternativa, que parece mais eficiente, uma vez que ele pare de ler a entrada quando a linha desejada é impresso, pode gerar um SIGPIPE no processo de alimentação, que por sua vez pode gerar uma mensagem de erro indesejado:

ls -l | sed -n -e '2{p;q}'

Eu vi que muitas vezes o suficiente para que eu costumo usar o primeiro (que é mais fácil de escrever, pelo menos), embora ls não é um comando que reclama quando fica SIGPIPE.

Para uma gama de linhas:

ls -l | sed -n 2,4p

Durante vários intervalos de linhas:

ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'

Outras dicas

ls -l | head -2 | tail -1

Alternativa à maneira agradável cabeça / cauda:

ls -al | awk 'NR==2'

ou

ls -al | sed -n '2p'

A partir sed1line :

# print line number 52
sed -n '52p'                 # method 1
sed '52!d'                   # method 2
sed '52q;d'                  # method 3, efficient on large files

A partir awk1line :

# print line number 52
awk 'NR==52'
awk 'NR==52 {print;exit}'          # more efficient on large files

Por uma questão de exaustividade; -)

curta código

find / | awk NR==3

vida mais curta

find / | awk 'NR==3 {print $0; exit}'

Tente esta versão sed:

ls -l | sed '2 ! d'

Ele diz "excluir todas as linhas que não são o segundo".

Você pode usar awk:

ls -l | awk 'NR==2'

Atualização

O código acima não vai conseguir o que queremos, porque de off-by-one de erro: o ls -l primeira linha de comando é o Total line. Para isso, o seguinte código revisto vai funcionar:

ls -l | awk 'NR==3'

é Perl facilmente disponíveis para você?

$ perl -n -e 'if ($. == 7) { print; exit(0); }'

Obviamente substituir qualquer número que você quer para o 7.

Outro cartaz sugerido

ls -l | head -2 | tail -1

mas se você cabeça tubo na cauda, ??parece que tudo até linha N é processado duas vezes.

cauda Piping na cabeça

ls -l | tail -n +2 | head -n1

seria mais eficiente?

Sim, a maneira mais eficiente (como já foi apontado por Jonathan Leffler) é usar sed com impressão e sair:

set -o pipefail                        # cf. help set
time -p ls -l | sed -n -e '2{p;q;}'    # only print the second line & quit (on Mac OS X)
echo "$?: ${PIPESTATUS[*]}"            # cf. man bash | less -p 'PIPESTATUS'

Hmm

sed não funcionou no meu caso. Proponho:

para linhas "impares" 1,3,5,7 ... ls | awk '0 == (NR + 1)% 2'

para linhas de "mesmo" 2,4,6,8 ls | awk '0 == (NR)% 2'

Para obter mais integralidade ..

ls -l | (for ((x=0;x<2;x++)) ; do read ; done ; head -n1)

Jogue fora as linhas até chegar ao segundo, em seguida, imprimir a primeira linha depois disso. Então, ele imprime a 3ª linha.

Se é apenas a segunda linha ..

ls -l | (read; head -n1)

Coloque como muitos 'ler do que necessário.

Eu adicionei isso no meu .bash_profile

function gdf(){
  DELETE_FILE_PATH=$(git log --diff-filter=D --summary | grep delete | grep $1 | awk '{print $4}')
  SHA=$(git log --all -- $DELETE_FILE_PATH | grep commit | head -n 1 | awk '{print $2}')
  git show $SHA -- $DELETE_FILE_PATH
}

E é obras

gdf <file name>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top