Як видалити новий рядок із рядка в Bash


110

У мене є така змінна.

echo "|$COMMAND|"

який повертається

|
REBOOT|

Як я можу видалити цей перший новий рядок?


7
Чому це позначено як дуп? Це питання стосується видалення повернення вагона. Передбачуваний дублікат питання, на який він посилається, стосується видалення пробілів, і лише випадково згадується про повернення каретки.
Майкл Шепер

1
@MichaelScheper погодився і знову відкрився.
fedorqui 'ТАК перестаньте шкодити'

Термінологія тут дивна. Символ завершення рядка Unix \n(hex 0x0A) називається каналом брехні (LF); він відрізняється від повернення каретки символів (CR) \r(hex 0x0D), який використовується в Windows та в багатьох мережевих протоколах як перший байт у двобайтовій послідовності закінчення рядка CR LF.
трійчатка

Відповіді:


114

Під , є деякі башизми:

trКоманда може бути замінена // bashism :

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

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

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

Див. Розширення параметрів та цитування на сторінці "bash man":

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|
Алекс Джордан

2
@AlexJordan Так, це бажана функція : Ви можете проскочити пробіл, \nщоб запобігти цьому: COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n']}|"повернеться |RE BOOT|.
Ф. Хаурі

2
Як працює шаблон ${COMMAND//[$'\t\r\n']}? Я думав, ${COMMAND//[\t\r\n]}що просто спрацює, але так не було. Що є $символом і одиничні цитати теж?
haridsv

1
Щодо синтаксису $ '', це цитування ANSI C (згадане у відповіді wjordans).
chuckx

81
echo "|$COMMAND|"|tr '\n' ' '

замінить нову лінію (в POSIX / Unix це не повернення каретки) пробілом.

Якщо чесно, я б подумав про перехід від bash до чогось більш здорового. Або взагалі уникати генерування цих неправильних даних.

Гммм, це здається, що це може бути і жахливий отвір безпеки, залежно від того, звідки беруться дані.


Дата надходить із запиту на згортання, який знаходиться на тому самому сервері. Як би я пішов про введення цього в новий var? newvar = $ (echo "| $ COMMAND |" | tr '\ n' '')
Matt Leyland

2
Так. Але скажіть, будь ласка, ви не дозволяєте довільним людям віддалено перезавантажувати ваш сервер без пароля ...
Робін Грін

31
Чому ви не використовували tr -d '\n'для краплі замість заміни пробілом
Ф. Хаурі

3
Будь ласка, потріскайте марні труби! Використовуйте tr '\n' ' ' <<< "|$COMMAND|"замістьecho ... | ...
Ф. Хаурі

12
@ F.Hauri: або марні тр:"|${COMMAND//$'\n'}|"
rici

75

Очистіть змінну, видаливши всі повернення перевезення:

COMMAND=$(echo $COMMAND|tr -d '\n')

22
Хіба це не смужка стрічки? Чи не повинен бути tr -d '\r'натомість?
Іззи

3
Ехо без коментованої змінної видаляє всі символи IFS (новий рядок, пробіл, вкладка за замовчуванням). Отже, якщо ви збираєтесь це робити, то ви повинні знати про те, що всі символи IFS скинуті, і вам це не потрібно tr. Просто COMMAND=$(echo $COMMAND)дасть подібний ефект. Це, мабуть, чорт нерест, оскільки він викликає новий процес, але він все ще досить короткий і милий для людських очей, і якщо у вас є ще секунда-дві, щоб пощадитись у своєму житті, ви можете бути готовими прийняти удар :-).
Майк S

Я оновив питання, щоб сказати "linefeed", оскільки його приклад показав, що це передача на лінії, а не повернення вагона. Ця відповідь все ще є правильною, але, можливо, її слід оновити, щоб сказати "linefeed" замість "повернення вагона"?
Бенджамін В.

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|

6

Що для мене працювало echo $testVar | tr "\n" " "

Де testVar містив мій змінний / скрипт-вихід


4

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

У моєму випадку я виявив, що команда, що закінчується awk-друком останнього елемента |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


2

Якщо ви використовуєте bash з увімкненою опцією extglob, ви можете видалити лише пробіл пробілу за допомогою:

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

Цей результат:

|
RE BOOT|

Або замініть %% на ##, щоб замінити лише провідний пробіл.


1
Це спрацювало як шарм із дивним результатом, який я отримав від команди докера. Дуже дякую!
develCuy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.