Как удалить новую строку из строки в Bash

110

У меня есть следующая переменная.

echo "|$COMMAND|"

который возвращается

|
REBOOT|

Как я могу удалить эту первую новую строку?

Мэтт Лейланд
источник
7
Почему это помечено как обман? Это вопрос об удалении возврата каретки. Предполагаемый повторяющийся вопрос, на который он ссылается, касается удаления пробелов и только вскользь упоминает возврат каретки.
Майкл Шепер,
1
@MichaelScheper согласился и снова открылся.
fedorqui 'SO stop harming'
Терминология здесь странная. Символ завершения строки Unix \n(шестнадцатеричный 0x0A) называется подачей лжи (LF); он отличается от символа возврата каретки (CR) \r(шестнадцатеричный 0x0D), который используется в Windows и во многих сетевых протоколах в качестве первого байта в двухбайтовой последовательности конца строки CR LF.
Tripleee

Ответы:

115

Под , есть некоторые башизмы:

trКоманда может быть заменена // bashism :

COMMAND=$'\nREBOOT\r   \n'
echo "|${COMMAND}|"
|
   OOT
|

echo "|${COMMAND//[$'\t\r\n']}|"
|REBOOT   |

echo "|${COMMAND//[$'\t\r\n ']}|"
|REBOOT|

См. Раздел « Расширение параметров» и « ЦИТАТИРОВАНИЕ» на странице руководства bash:

man -Pless\ +/\/pattern bash
man -Pless\ +/\\\'string\\\' bash

man -Pless\ +/^\\\ *Parameter\\\ Exp bash
man -Pless\ +/^\\\ *QUOTING bash

Дальше...

По запросу @AlexJordan, это подавит все указанные символы. Так что, если $COMMANDесть пробелы ...

COMMAND=$'         \n        RE BOOT      \r           \n'
echo "|$COMMAND|"
|
           BOOT      
|

CLEANED=${COMMAND//[$'\t\r\n']}
echo "|$CLEANED|"
|                 RE BOOT                 |

shopt -q extglob || { echo "Set shell option 'extglob' on.";shopt -s extglob;}

CLEANED=${CLEANED%%*( )}
echo "|$CLEANED|"
|                 RE BOOT|

CLEANED=${CLEANED##*( )}
echo "|$CLEANED|"
|RE BOOT|

Вскоре:

COMMAND=$'         \n        RE BOOT      \r           \n'
CLEANED=${COMMAND//[$'\t\r\n']} && CLEANED=${CLEANED%%*( )}
echo "|${CLEANED##*( )}|"
|RE BOOT|

Примечание: есть extglobопция, которая должна быть включена ( shopt -s extglob) для использования *(...)синтаксиса.

Ф. Хаури
источник
1
Это способ убрать перевод строки из переменной в BASH. Другие ответы без нужды вызывают дополнительный процесс TR. Кстати, у него есть дополнительное преимущество - удаление конечных пробелов!
ingyhere
1
Обратите внимание, что он также удаляет внутренние пробелы из строки ... COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n ']}|"возвращается|REBOOT|
Alex Jordan
2
@AlexJordan Да, это желаемая функция : вы можете взбить пространство после, \nчтобы предотвратить это: COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n']}|"вернется |RE BOOT|.
F. Hauri
2
Как работает узор ${COMMAND//[$'\t\r\n']}? Думал ${COMMAND//[\t\r\n]}просто сработает, но не вышло. Для чего нужен $символ и одинарные кавычки?
haridsv
1
Что касается синтаксиса $ '', это цитирование ANSI C (упоминается в ответе wjordans).
chuckx
81
echo "|$COMMAND|"|tr '\n' ' '

заменит новую строку (в POSIX / Unix это не возврат каретки) пробелом.

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

Хммм, похоже, это также может быть ужасная дыра в безопасности, в зависимости от того, откуда поступают данные.

Робин Грин
источник
Дата исходит из запроса curl, который находится на том же сервере, как я могу поместить это в новый var? newvar = $ (echo "| $ COMMAND |" | tr '\ n' '')
Мэтт Лейланд
2
Да. Но, пожалуйста, скажите мне, что вы не позволяете произвольным людям перезагружать ваш сервер удаленно без пароля ...
Робин Грин
32
Почему вы не использовали tr -d '\n'для сброса вместо замены пробелом
Ф. Хаури
3
Пожалуйста, протрите бесполезные трубы! Использовать tr '\n' ' ' <<< "|$COMMAND|"вместоecho ... | ...
Ф. Хаури
12
@ F.Hauri: или бесполезные tr's:"|${COMMAND//$'\n'}|"
rici
76

Очистите переменную, удалив все символы возврата каретки:

COMMAND=$(echo $COMMAND|tr -d '\n')
Максим Шерами
источник
22
Разве эта полоса не переводит строку? Разве это не должно быть tr -d '\r'вместо этого?
Иззи
3
Отображение раскомментированной переменной удаляет все символы IFS (новая строка, пробел, табуляция по умолчанию). Поэтому, если вы собираетесь это сделать, вы должны знать, что все символы IFS отброшены, и вам не нужен tr. Просто COMMAND=$(echo $COMMAND)даст аналогичный эффект. Это, по-видимому, порождение дьявола, поскольку оно вызывает новый процесс, но он все еще довольно короткий и приятный для человеческого глаза, и если у вас есть лишняя секунда или две в вашей жизни, вы можете принять удар :-).
Mike S
Я обновил вопрос, чтобы сказать «перевод строки», поскольку его пример действительно показал, что это был перевод строки, а не возврат каретки. Этот ответ по-прежнему верен, но, возможно, его следует обновить, чтобы он сказал «перевод строки» вместо «возврат каретки»?
Бенджамин В.
8

Использование bash:

echo "|${COMMAND/$'\n'}|"

(Обратите внимание, что управляющий символ в этом вопросе - это «новая строка» ( \n), а не возврат каретки ( \r); последний будет выводиться REBOOT|в одной строке.)

Объяснение

Использует расширение параметров оболочки Bash ${parameter/pattern/string}:

Шаблон расширяется , чтобы получить шаблон так же , как в расширении имени файла. Параметр раскрывается, и самое длинное совпадение шаблона с его значением заменяется строкой . [...] Если строка равна нулю, совпадения с шаблоном удаляются, и следующий / / шаблон может быть опущен.

Также использует конструкцию $'' цитирования ANSI-C для указания новой строки как $'\n'. Непосредственное использование новой строки также будет работать, хотя и менее красиво:

echo "|${COMMAND/
}|"

Полный пример

#!/bin/bash
COMMAND="$'\n'REBOOT"
echo "|${COMMAND/$'\n'}|"
# Outputs |REBOOT|

Или, используя символы новой строки:

#!/bin/bash
COMMAND="
REBOOT"
echo "|${COMMAND/
}|"
# Outputs |REBOOT|
Wjordan
источник
6

Для меня сработало echo $testVar | tr "\n" " "

Где testVar содержал мою переменную / вывод сценария

Prachi
источник
4

Добавление ответа, чтобы показать пример удаления нескольких символов, включая \ r, с помощью tr и с помощью sed. И проиллюстрировал использование hexdump.

В моем случае я обнаружил, что команда, оканчивающаяся на awk print последнего элемента |awk '{print $2}'в строке, включает возврат каретки \ r, а также кавычки.

Раньше я sed 's/["\n\r]//g'удалял и возврат каретки, и кавычки.

Я тоже мог использовать tr -d '"\r\n'.

Интересное замечание sed -zнеобходимо, если кто-то хочет удалить символы перевода строки \ n.

$ COMMAND=$'\n"REBOOT"\r   \n'

$ echo "$COMMAND" |hexdump -C
00000000  0a 22 52 45 42 4f 4f 54  22 0d 20 20 20 0a 0a     |."REBOOT".   ..|

$ echo "$COMMAND" |tr -d '"\r\n' |hexdump -C
00000000  52 45 42 4f 4f 54 20 20  20                       |REBOOT   |

$ echo "$COMMAND" |sed 's/["\n\r]//g' |hexdump -C
00000000  0a 52 45 42 4f 4f 54 20  20 20 0a 0a              |.REBOOT   ..|

$ echo "$COMMAND" |sed -z 's/["\n\r]//g' |hexdump -C
00000000  52 45 42 4f 4f 54 20 20  20                       |REBOOT   |

И это актуально: что такое возврат каретки, перевод строки и перевод страницы?

  • CR == \ r == 0x0d
  • LF == \ n == 0x0a
Gaoithe
источник
3

Вы можете просто использовать echo -n "|$COMMAND|".

Пауло
источник
2

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

shopt -s extglob
COMMAND=$'\nRE BOOT\r   \n'
echo "|${COMMAND%%*([$'\t\r\n '])}|"

Это выводит:

|
RE BOOT|

Или замените %% на ##, чтобы заменить только ведущий пробел.

zeroimpl
источник
1
Это сработало как шарм с каким-то странным выводом, который я получил от команды докера. Большое спасибо!
develCuy