Comando para obter linha enésima de STDOUT
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.
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'
Por uma questão de exaustividade; -)
curta código
find / | awk NR==3
vida mais curta ??p>
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>