Bash: Смугайте стрибковий рядок від виводу


189

Коли я виконую команди в Bash (або бути конкретнішим, wc -l < log.txt), висновок містить рядковий рядок після нього. Як я його позбудуся?

Відповіді:


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' від coreutils GNU, щоб вибрати все, крім останнього байта. Це має бути досить швидким:

head -c -1 log.txt

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

cat -A log.txt

Це знімає ВСІ нові рядки з результату, а не лише останній рядок, як запитує заголовок.
Коді А. Рей

@ CodyA.Ray: Ви повинні погодитися, що питання описує конкретну команду, яка коли-небудь створюватиме лише один рядок виводу. Однак я оновив свою відповідь, щоб відповідати більш загальній справі. HTH.
Стів

3
Це було б краще, якби короткі варіанти замінили довгими. Довгі варіанти вчать, а також функціонують, наприклад tr --delete '\n'.
Ілля Лінн

1
Я теж зробив| tr -d '\r'
АлікЕльзін-кілака

Варто зазначити, що рішення заміщення cmd може призвести до надмірного рядка, якщо файл дуже великий.
phk

88

Односторонній:

wc -l < log.txt | xargs echo -n

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`

10
Точні нові рядки позбавлені, якщо бути точним. Саме підміна команд видаляє їх, а не присвоєння змінної.
чепнер

2
Я бачив у Cygwin bash, що проміжок білого простору не видаляється при використанні $ (cmd / c echo% VAR%). У цьому випадку мені довелося використовувати $ {var %% [[: space:]]}.
Андрій Таранов

1
Зауважте: видалення нових рядків не є призначенням змінної, а розширенням виразу.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

10

printf вже обробляє останній новий рядок для вас:

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

Детальніше:

  • printf надрукує ваш вміст %sзамість власника місця рядка.
  • Якщо ви не скажете йому надрукувати новий рядок ( %s\n), він не стане.

7
Якщо поставити подвійні лапки навколо команди , як "$(command)", внутрішні переклади рядка будуть збережені - і тільки задня новий рядок буде видалена. Оболонка робить всю роботу тут - printfце лише спосіб спрямувати результати заміни команд назад stdout.
Брент Бредберн

2
Зняти нову лінію тут не printf, це оболонка, яка робить це з $( )конструктом. Ось доказ:printf "%s" "$(perl -e 'print "\n"')"
Flimm

Знову ж таки, варто відзначити, що в результаті командний рядок може стати занадто довгим.
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)має той же ефект.
чепнер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.