Bash: убрать разрыв строки из вывода

189

Когда я выполняю команды в Bash (или, если быть точным, wc -l < log.txt ), вывод содержит перевод строки после него. Как мне от этого избавиться?

hexacyanide
источник

Ответы:

251

Если ожидаемый результат - одна строка , вы можете просто удалить все символы новой строки из вывода. Было бы весьма необычно передавать по конвейеру утилиту 'tr' или Perl, если это предпочтительно:

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

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

Вы также можете использовать подстановку команд для удаления завершающей строки:

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

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

Обратите внимание, что я не согласен с решением ФП о выборе принятого ответа. Я считаю, что по возможности следует избегать использования xargs. Да, это крутая игрушка. Нет, тебе здесь это не нужно.


Если ожидаемый результат может содержать несколько строк , вам нужно принять другое решение:

Если вы хотите удалить НЕСКОЛЬКО символов новой строки из конца файла, снова используйте подстановку cmd:

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

Если вы хотите строго удалить символ последней строки из файла, используйте Perl:

perl -pe 'chomp if eof' log.txt


Обратите внимание, что если вы уверены, что у вас есть завершающий символ новой строки, который вы хотите удалить, вы можете использовать 'head' из GNU coreutils, чтобы выбрать все, кроме последнего байта. Это должно быть довольно быстро:

head -c -1 log.txt

Также, для полноты, вы можете быстро проверить, где находятся ваши символы новой строки (или другие специальные символы) в вашем файле, используя 'cat' и флаг 'show-all'. Знак доллара будет обозначать конец каждой строки:

cat -A log.txt
Стив
источник
Это удаляет ВСЕ новые строки из выходных данных, а не только завершающую новую строку, как просит заголовок.
Коди А. Рэй
@ CodyA.Ray: Вы должны согласиться с тем, что этот вопрос описывает конкретную команду, которая будет когда-либо производить только одну строку вывода. Я, однако, обновил свой ответ, чтобы удовлетворить более общий случай. НТН.
Стив
3
Это было бы лучше, если бы короткие варианты были заменены длинными. Длинные опции учат так же, как функционируют, например tr --delete '\n'.
Элайджа Линн
1
Я тоже сделал| tr -d '\r'
АликЭльзин-килака
Стоит отметить, что решение подстановки cmd может привести к слишком длинной строке, если файл очень большой.
PHK
88

В одну сторону:

wc -l < log.txt | xargs echo -n
Satya
источник
24
Лучше:echo -n `wc -l log.txt`
Сатья
9
Почему выполнение команд в обратных тиках лучше, чем использование канала?
Мэтью Шинкель
2
Они не только удаляют завершающие символы новой строки, но также сжимают любые последовательные пробелы (точнее, как определено IFS) в одном месте. Пример echo "a b" | xargs echo -n:; echo -n $(echo "a b"), Это может или не может быть проблемой для варианта использования.
Musiphil
14
Хуже того, если вывод начинается с -e, он будет интерпретирован как опция echo. Это всегда безопаснее в использовании printf '%s'.
Musiphil
1
xargsВ моей системе это происходит очень медленно (и я подозреваю, что это происходит и в других системах), поэтому printf '%s' $(wc -l log.txt)может быть быстрее, поскольку printfобычно является встроенным (также из-за отсутствия перенаправления информации). Никогда не используйте обратные пометки, они устарели в новых версиях POSIX и имеют многочисленные недостатки.
yyny
14

Существует также прямая поддержка удаления пробелов в подстановке переменных Bash :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
Андрей Таранов
источник
1
Вы также можете использоватьtrailing_linebreak_removed=${testvar%?}
PairedPrototype
Обратите внимание, что если вы используете подстановку команд, вам не нужно ничего делать, чтобы удалить завершающие символы новой строки. Bash уже делает это как часть подстановки команд: gnu.org/software/bash/manual/html_node/…
Майкл Барр
10

Если вы назначите ее вывод переменной, bashавтоматически удаляются пробелы:

linecount=`wc -l < log.txt`
nneonneo
источник
10
Конечные переводы строки, если быть точным, удалены. Их удаляет подстановка команд, а не присвоение переменных.
Чепнер
2
Я видел в Cygwin bash конечный пробел, который не удалялся при использовании $ (cmd / c echo% VAR%). В этом случае мне пришлось использовать $ {var %% [[: space:]]}.
Андрей Таранов
1
Примечание: это не присвоение переменной, а расширение выражения, которое удаляет символы новой строки.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
10

printf уже обрезает завершающий символ новой строки для вас:

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

Деталь:

  • printf напечатает ваш контент вместо %sстрокового заполнителя.
  • Если вы не скажете ему напечатать символ новой строки ( %s\n), он не будет.
zero2cx
источник
7
Если вы поместите двойные кавычки вокруг команды, как "$(command)", внутренние переводы будут сохранены - и будет удален только завершающий перевод строки. Оболочка выполняет всю работу здесь - printfэто просто способ вернуть результаты подстановки команд обратно stdout.
Брент Брэдберн
2
Здесь не printf разбирает новую строку, а оболочка, которая делает это с помощью $( )конструкции. Вот доказательство:printf "%s" "$(perl -e 'print "\n"')"
Флимм
Опять же, стоит отметить, что получающаяся командная строка может стать слишком длинной.
PHK
Это удобное решение с предложением @ nobar:$ printf '%s' "$(wc -l < log.txt)"
Илиас Карим
10

Если вы хотите удалить только последний символ новой строки , пройдите через:

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

sedне добавит a \0к концу потока, если для разделителя задано значение NULvia -z, тогда как для создания текстового файла POSIX (с определением конца a \n) он всегда будет выводить финал \nбез-z .

Например:

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

И доказать не NULдобавил

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

Чтобы удалить несколько завершающих символов новой строки , проложите через:

sed -Ez '$ s/\n+$//'
Том Хейл
источник
Я предполагаю, что это расширение GNU, Mac sedне предоставляет -z.
Spidey
7

Если вы хотите напечатать вывод чего-либо в Bash без конца строки, вы должны повторить это с помощью -n переключателя.

Если он уже есть в переменной, отобразите его с завершающим символом новой строки :

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

Или вы можете сделать это в одной строке:

    $ echo -n $(wc -l < log.txt)
Растислав Хасичек
источник
2
Переменная технически не нужна. echo -n $(wc -l < log.txt)имеет тот же эффект.
Чепнер