Как удалить новую строку из строки в Bash
У меня есть следующая переменная.
echo "|$COMMAND|"
который возвращается
|
REBOOT|
Как я могу удалить эту первую новую строку?
12 ответов
echo "|$COMMAND|"|tr '\n' ' '
заменит символ новой строки (в POSIX/Unix это не возврат каретки) пробелом.
Если честно, я бы подумал о том, чтобы переключиться с bash на что-то более вменяемое. Или избегать генерации этих искаженных данных.
Хм, похоже, это может быть ужасная дыра в безопасности, в зависимости от того, откуда поступают данные.
Под Bash есть несколько bashisms:
tr
команда может быть заменена //
Башизм:
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
) чтобы использовать *(...)
синтаксис.
Очистите переменную, удалив все возвраты каретки:
COMMAND=$(echo $COMMAND|tr -d '\n')
С помощью 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|
Добавление ответа, чтобы показать пример удаления нескольких символов, включая \ r, используя tr и sed. И иллюстрируя с помощью hexdump.
В моем случае я обнаружил, что команда, заканчивающаяся awk print последнего элемента |awk '{print $2}'
в строку включены возврат каретки и кавычки.
я использовал 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
Что сработало для меня echo $testVar | tr "\n" " "
Где testVar содержал мою переменную / скрипт-вывод
Используйте этот бред, если вы не хотите создавать такие процессы, как (tr, sed или awk) для такой простой задачи. Bash может сделать это самостоятельно:
COMMAND=${COMMAND//$'\n'/}
Из документации:
${FOO//from/to} Replace all
${FOO/from/to} Replace first match
Если вы используете bash с включенной опцией extglob, вы можете удалить только конечный пробел через:
shopt -s extglob
COMMAND=$'\nRE BOOT\r \n'
echo "|${COMMAND%%*([$'\t\r\n '])}|"
Это выводит:
|
RE BOOT|
Или замените %% на ##, чтобы заменить только первые пробелы.
Чтобы устранить один возможный корень фактической проблемы, есть вероятность, что вы используете файл crlf.
Пример CRLF:
.env (crlf)
запустить.ш
Возвращает:
abc
def
def
Однако, если вы конвертируете в LF:
.env (лф)
VARIABLE_A="abc"
VARIABLE_B="def"
запустить.ш
#!/bin/bash
source .env
echo "$VARIABLE_A"
echo "$VARIABLE_B"
echo "$VARIABLE_A $VARIABLE_B"
Возвращает:
abc
def
abc def
Обратите внимание, что оболочка уже сделает это за вас, если вы пройдете$COMMAND
как параметр вместо строки.
Итак, вы можете попробовать это:
COMMAND="a
b
c"
echo $COMMAND
Чтобы добавить каналы, вы можете просто использовать кавычки без пробелов, например:
echo "|"$COMMAND"|"
работает отлично и немного проще, чем другие решения. Это также работает только с/bin/sh
.
Grep можно использовать для фильтрации любых пустых строк. Это полезно, если у вас есть несколько строк данных и вы хотите удалить все пустые.
echo "$COMMAND" | grep .