Как удалить новую строку из строки в 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|

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

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

Чтобы устранить один возможный корень фактической проблемы, есть вероятность, что вы используете файл 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 .
Другие вопросы по тегам