Bash: supprimer le saut de ligne de fin de la sortie

189

Lorsque j'exécute des commandes dans Bash (ou pour être plus précis wc -l < log.txt), la sortie contient un saut de ligne après. Comment m'en débarrasser?

hexacyanide
la source

Réponses:

251

Si votre sortie attendue est une seule ligne , vous pouvez simplement supprimer tous les caractères de nouvelle ligne de la sortie. Il ne serait pas rare de diriger vers l'utilitaire 'tr', ou vers Perl si vous préférez:

wc -l < log.txt | tr -d '\n'

wc -l < log.txt | perl -pe 'chomp'

Vous pouvez également utiliser la substitution de commande pour supprimer la nouvelle ligne de fin:

echo -n "$(wc -l < log.txt)"

printf "%s" "$(wc -l < log.txt)"

Veuillez noter que je ne suis pas d'accord avec la décision du PO de choisir la réponse acceptée. Je pense qu'il faut éviter d'utiliser «xargs» lorsque cela est possible. Oui, c'est un jouet sympa. Non, vous n'en avez pas besoin ici.


Si votre sortie attendue peut contenir plusieurs lignes , vous avez une autre décision à prendre:

Si vous souhaitez supprimer MULTIPLES caractères de nouvelle ligne à la fin du fichier, utilisez à nouveau la substitution cmd:

printf "%s" "$(< log.txt)"

Si vous souhaitez supprimer strictement LE DERNIER caractère de nouvelle ligne d'un fichier, utilisez Perl:

perl -pe 'chomp if eof' log.txt


Notez que si vous êtes certain d'avoir un caractère de fin de ligne à supprimer, vous pouvez utiliser «head» de GNU coreutils pour tout sélectionner sauf le dernier octet. Cela devrait être assez rapide:

head -c -1 log.txt

De plus, pour être complet, vous pouvez rapidement vérifier où se trouvent vos caractères de nouvelle ligne (ou autres caractères spéciaux) dans votre fichier en utilisant «cat» et l'indicateur «show-all». Le caractère signe dollar indiquera la fin de chaque ligne:

cat -A log.txt
Steve
la source
Cela supprime TOUTES les nouvelles lignes de la sortie, pas seulement la nouvelle ligne de fin comme le titre le demande.
Cody A. Ray
@ CodyA.Ray: Vous devez cependant convenir que la question décrit une commande spécifique qui ne produira jamais qu'une seule ligne de sortie. J'ai cependant mis à jour ma réponse pour l'adapter au cas plus général. HTH.
Steve
3
Ce serait mieux si les options courtes étaient remplacées par des options longues. Les options longues enseignent ainsi que fonctionnent par exemple tr --delete '\n'.
Elijah Lynn le
1
J'ai aussi fait| tr -d '\r'
AlikElzin-kilaka
Il convient de noter que la solution de substitution cmd peut conduire à une ligne trop longue si le fichier est très volumineux.
phk
88

Une manière:

wc -l < log.txt | xargs echo -n
Satya
la source
24
Mieux:echo -n `wc -l log.txt`
Satya
9
Pourquoi est-il préférable d'exécuter des commandes dans des backticks plutôt que d'utiliser un tube?
Matthew Schinckel
2
Celles-ci supprimeront non seulement les nouvelles lignes de fin, mais réduiront également tous les espaces consécutifs (plus précisément, comme défini par IFS) à un espace. Exemple echo "a b" | xargs echo -n:; echo -n $(echo "a b"). Cela peut ou non être un problème pour le cas d'utilisation.
musiphil
14
Pire encore, si la sortie commence par -e, elle sera interprétée comme l'option de echo. C'est toujours plus sûr à utiliser printf '%s'.
musiphil
1
xargsest très lent sur mon système (et je soupçonne que c'est aussi sur d'autres systèmes), donc printf '%s' $(wc -l log.txt)peut-être plus rapide, car il printfs'agit généralement d'une fonction intégrée (également parce qu'il n'y a pas de redirection d'informations). N'utilisez jamais de backticks, ils sont obsolètes dans les nouvelles versions de POSIX et présentent de nombreux inconvénients.
yyny
14

Il existe également un support direct pour la suppression des espaces blancs dans la substitution de variables Bash :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
Andrey Taranov
la source
1
Vous pouvez également utilisertrailing_linebreak_removed=${testvar%?}
PairedPrototype
Notez que si vous utilisez la substitution de commande, vous n'avez rien à faire pour supprimer les nouvelles lignes de fin. Bash fait déjà cela dans le cadre de la substitution de commandes: gnu.org/software/bash/manual/html_node/…
Michael Burr
10

Si vous affectez sa sortie à une variable, bashsupprime automatiquement les espaces:

linecount=`wc -l < log.txt`
nneonneo
la source
10
Les nouvelles lignes de fin sont supprimées, pour être exact. C'est la substitution de commande qui les supprime, pas l'affectation de variable.
chepner
2
J'ai vu dans Cygwin bash les espaces de fin non supprimés lors de l'utilisation de $ (cmd / c echo% VAR%). Dans ce cas, j'ai dû utiliser $ {var %% [[: space:]]}.
Andrey Taranov
1
Remarque: ce n'est pas l'affectation de variable, mais le développement d'expression qui supprime les nouvelles lignes.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
10

printf coupe déjà la nouvelle ligne de fin pour vous:

$ printf '%s' $(wc -l < log.txt)

Détail:

  • printf imprimera votre contenu à la place de l' %sespace réservé à la chaîne.
  • Si vous ne lui dites pas d'imprimer une nouvelle ligne ( %s\n), ce ne sera pas le cas.
zero2cx
la source
7
Si vous mettez des guillemets doubles autour de la commande comme "$(command)", les retours à la ligne internes seront conservés - et seul le retour à la ligne de fin sera supprimé. Le shell fait tout le travail ici - printfc'est juste un moyen de renvoyer les résultats de la substitution de commande vers stdout.
Brent Bradburn
2
Ce n'est pas printf qui supprime la nouvelle ligne ici, c'est le shell qui le fait avec la $( )construction. Voici la preuve:printf "%s" "$(perl -e 'print "\n"')"
Flimm
Encore une fois, il convient de noter que la ligne de commande résultante peut devenir trop longue.
phk
C'est une solution pratique avec la suggestion de @ nobar:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim
10

Si vous souhaitez supprimer uniquement la dernière nouvelle ligne , passez par:

sed -z '$ s/\n$//'

sedn'ajoutera pas \0de fin à puis du flux si le délimiteur est défini sur NULvia -z, alors que pour créer un fichier texte POSIX (défini pour se terminer par a \n), il produira toujours un final \nsans-z .

Par exemple:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

Et pour prouver non NULajouté:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

Pour supprimer plusieurs nouvelles lignes de fin , passez par:

sed -Ez '$ s/\n+$//'
Tom Hale
la source
Je suppose que c'est une extension GNU, Mac sedne fournit pas -z.
Spidey
7

Si vous voulez imprimer la sortie de quoi que ce soit dans Bash sans fin de ligne, vous en faites l'écho avec le -n commutateur.

Si vous l'avez déjà dans une variable, faites-en l'écho avec la nouvelle ligne de fin recadrée:

    $ testvar=$(wc -l < log.txt)
    $ echo -n $testvar

Ou vous pouvez le faire en une seule ligne, à la place:

    $ echo -n $(wc -l < log.txt)
Rastislav Hasicek
la source
2
La variable est techniquement inutile. echo -n $(wc -l < log.txt)a le même effet.
chepner