如何从 Bash 中的字符串中删除换行符

问题描述 投票:0回答:11

我有以下变量。

echo "|$COMMAND|"

返回

|
REBOOT|

我怎样才能删除第一个换行符?

bash variables
11个回答
171
投票

字符串中,字符替换/删除

下,有一些bashism

tr
命令可以替换为
${parameter/pattern/string}
bashism

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

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

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

参见 bash 手册页中的Parameter ExpansionQUOTING

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

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

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

进一步...

正如@AlexJordan 所问,这将抑制all 指定的字符。那么如果

$COMMAND
包含空格怎么办...

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

read -r COMMAND <<<"${COMMAND//[$'\t\r\n']}"
echo "|$COMMAND|"
|RE BOOT|

避免fork
tr
单弦!

比较一下:

COMMAND=$'\nREBOOT\r   \n'
echo ${COMMAND@Q}
$'\nREBOOT\r \n'

COMMAND=$(echo $COMMAND|tr -d '\n\t\r ')
echo ${COMMAND@Q}
'REBOOT'

然后

time for i in {1..1000};do
    COMMAND=$'\nREBOOT\r   \n'
    COMMAND=$(echo $COMMAND|tr -d '\n\t\r ')
done;echo ${COMMAND@Q}

real    0m2.785s
user    0m2.296s
sys     0m0.774s
'REBOOT'

COMMAND=$'\nREBOOT\r   \n'
COMMAND="${COMMAND//[$'\t\r\n ']}"
echo ${COMMAND@Q}

time for i in {1..1000};do
    COMMAND=$'\nREBOOT\r   \n'
    COMMAND="${COMMAND//[$'\t\r\n ']}"
done;echo ${COMMAND@Q}

real    0m0.006s
user    0m0.001s
sys     0m0.004s
'REBOOT'

tr
进行 1'000 次分叉在我的主机上花费了超过 2700 毫秒,而通过使用 内置 bash 参数扩展!!,同样的工作在 6 毫秒内完成(快 464.2 倍!!


116
投票

通过删除所有换行符来清理变量:

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

108
投票
echo "|$COMMAND|"|tr '\n' ' '

将用空格替换换行符(在 POSIX/Unix 中它不是回车符)。

老实说,我会考虑从 bash 切换到更理智的东西。或者首先避免生成这种格式错误的数据。

嗯,这似乎也可能是一个可怕的安全漏洞,具体取决于数据的来源。


15
投票

使用

bash

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

(注意这道题的控制符是换行符(

\n
),不是回车符(
\r
);后者会在单行输出
REBOOT|
。)

说明

使用 Bash Shell 参数扩展

${parameter/pattern/string}

pattern 被扩展以产生一个模式,就像在文件名扩展中一样。 Parameter 被扩展并且 pattern 与其值的最长匹配被替换为 string。 [...]如果string为空,则删除pattern的匹配项,并且可以省略pattern之后的/

还使用

$''
ANSI-C quoting 构造将换行符指定为
$'\n'
。直接使用换行符也可以,尽管不那么漂亮:

echo "|${COMMAND/
}|"

完整示例

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

或者,使用换行符:

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

12
投票

添加答案以显示剥离多个字符的示例,包括 使用 tr 和使用 sed。 并说明使用 hexdump.

在我的例子中,我发现以行中最后一项

|awk '{print $2}'
的awk打印结尾的命令包括回车 以及引号。

我用

sed 's/["\n\r]//g'
去掉回车和引号。

我也可以用

tr -d '"\r\n'
.

有趣的注意

sed -z
如果想要删除 换行字符。

$ 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== == 0x0d
  • 低频== == 0x0a

10
投票

对我有用的是

echo $testVar | tr "\n" " "

testVar 包含我的变量/脚本输出


5
投票

如果您在启用 extglob 选项的情况下使用 bash,您可以通过以下方式仅删除尾随空格:

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

这输出:

|
RE BOOT|

或者将 %% 替换为 ## 以仅替换前导空格。


4
投票

你可以简单地使用

echo -n "|$COMMAND|"
.

$ man echo

-n
不输出尾随的换行符


2
投票

为了解决实际问题的一个可能根源,您有可能正在采购 crlf 文件。

CRLF 示例:

.env(crlf)

VARIABLE_A="abc"
VARIABLE_B="def"

run.sh

#!/bin/bash
source .env
echo "$VARIABLE_A"
echo "$VARIABLE_B"
echo "$VARIABLE_A $VARIABLE_B"

退货:

abc
def
 def

如果你转换为 LF:

.env (lf)

VARIABLE_A="abc"
VARIABLE_B="def"

run.sh

#!/bin/bash
source .env
echo "$VARIABLE_A"
echo "$VARIABLE_B"
echo "$VARIABLE_A $VARIABLE_B"

退货:

abc
def
abc def

1
投票

如果您不想为这样一个简单的任务生成像(tr、sed 或 awk)这样的进程,请使用此 bashism。 Bash 可以单独完成:

COMMAND=${COMMAND//$'\n'/}

来自文档:

${FOO//from/to} Replace all
${FOO/from/to}  Replace first match

-1
投票

Grep 可用于过滤掉任何空行。如果您有几行数据并且想要删除任何空数据,这将很有用。

echo "$COMMAND" | grep .
© www.soinside.com 2019 - 2024. All rights reserved.