Avoir la tête afin d'afficher toutes les mais la dernière ligne d'un fichier: la substitution de commande et d'e/S standard de redirection
J'ai essayé d'obtenir la head
utilitaire pour afficher toutes les mais la dernière ligne de l'entrée standard. Le code que j'ai besoin est quelque chose le long des lignes de cat myfile.txt | head -n $(($(wc -l)-1))
. Mais cela ne fonctionne pas. Je fais cela sur Darwin/OS X, qui n'a pas la belle et la sémantique de head -n -1
qui aurait réussi à me faire le même résultat.
Aucune de ces variations travail.
cat myfile.txt | head -n $(wc -l | sed -E -e 's/\s//g')
echo "hello" | head -n $(wc -l | sed -E -e 's/\s//g')
J'ai testé plus de variations et, en particulier, de ce travail:
cat <<EOF | echo $(($(wc -l)-1))
>Hola
>Raul
>Como Esta
>Bueno?
>EOF
3
Voici quelque chose de plus simple qui fonctionne également.
echo "hello world" | echo $(($(wc -w)+10))
Ce une manière compréhensible me donne illégale d'un nombre de lignes d'erreur. Mais c'est au moins me dit que le head
programme ne consomme pas de l'entrée standard avant de passer à des trucs sur le shell interne est exécuté/la substitution de commande, une possibilité éloignée, mais celui que je voulais à la règle de toute façon.
echo "hello" | head -n $(cat && echo 1)
Ce qui explique le comportement de head
et wc
et leur interaction à travers la sous-coquille ici? Merci pour votre aide.
Vous devez vous connecter pour publier un commentaire.
head
est le mauvais outil. Si vous voulez voir toutes les mais la dernière ligne, l'utilisation:La raison que
échoue, c'est que
wc
consomme la totalité de l'entrée et il n'y a rien à gauche pourhead
à voir.wc
hérite de son stdin à partir du shell interne est exécuté dans lequel il est exécuté, ce qui est de la lecture à partir de la sortie de laecho
. Une fois qu'il consomme de l'entrée, il retourne puishead
essaie de lire les données...mais il est parti. Si vous voulez lire l'entrée deux fois, les données doivent être stockées quelque part.sed
, mais dans cette question, je suis précisément en essayant de comprendre pourquoi l'approche à l'aidehead
ne fonctionne pas.sed
script est absolument correct, solution portable, et je ne trouve pas de faille dans l'explication.sed
solution qui n'abordent pas la question du tout.head -n -1
vous donnera tous sauf la dernière ligne de son entrée.head
qui prend en charge que de la syntaxe. Pas tous les faire.head -n -1
.À l'aide de sed:
sera de supprimer la dernière ligne du fichier.
head
solutions indiquées, cesed
méthode fonctionne sur FreeBSD.Pour Mac OS X en particulier, j'ai trouvé une réponse à partir d'un commentaire à ce Q&A.
En supposant que vous utilisez Homebrew, exécutez
brew install coreutils
puis utilisez leghead
commande:Ou, de manière équivalente:
Enfin, voir
brew info coreutils
si vous souhaitez utiliser les commandes sans lesg
préfixe (p. ex.,head
au lieu deghead
).Cela fonctionne. C'est trop compliqué: vous pouvez simplement écrire
echo $(($(wc -l)-1)) <myfile.txt
ouecho $(($(wc -l <myfile.txt)-1))
. Le problème est la façon dont vous l'utilisez.wc
consomme tous les commentaires que c'est en comptant les lignes. Donc, il n'y a pas de données de gauche à lire dans le tuyau par le tempshead
est commencé.Si votre entrée est livré à partir d'un fichier, vous pouvez rediriger les deux
wc
ethead
à partir de ce fichier.Si vos données peuvent provenir d'une pipe, vous avez besoin de le dupliquer. L'habitude de l'outil pour dupliquer un flux est
tee
, mais ça ne suffit pas ici, parce que les deux sorties detee
sont produites à la même vitesse, alors qu'iciwc
doit pleinement consommer sa sortie avant dehead
peut commencer. Donc, au lieu de cela, vous aurez besoin d'utiliser un outil unique qui permet de détecter la dernière ligne, ce qui est une approche plus efficace de toute façon.Idéalement, sed offre un moyen de répondre à la dernière ligne. Soit les imprimer toutes les lignes sauf la dernière, ou la suppression de la dernière ligne de sortie, va travailler:
Pour ce travail, un awk one-liner est un peu plus long qu'un sed un.