简体   繁体   English

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

[英]How to remove a newline from a string in Bash

I have the following variable.我有以下变量。

echo "|$COMMAND|"

which returns返回

|
REBOOT|

How can I remove that first newline?如何删除第一个换行符?

Under , there are some bashisms:下,有一些 bashisms:

The tr command could be replaced by // bashism : tr命令可以替换为// bashism

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

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

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

See Parameter Expansion and QUOTING in bash's man page:请参阅 bash 手册页中的参数扩展引用

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

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

Further...更远...

As asked by @AlexJordan, this will suppress all specified characters.正如@AlexJordan 所问,这将抑制所有指定的字符。 So what if $COMMAND do contain spaces...那么如果$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|

Shortly:不久:

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

Note: have extglob option to be enabled ( shopt -s extglob ) in order to use *(...) syntax.注意: 启用了extglob选项( shopt -s extglob )以便使用*(...)语法。

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

will replace the newline (in POSIX/Unix it's not a carriage return) with a space.将用空格替换换行符(在 POSIX/Unix 中它不是回车符)。

To be honest I would think about switching away from bash to something more sane though.老实说,我会考虑从 bash 切换到更理智的东西。 Or avoiding generating this malformed data in the first place.或者首先避免生成这种格式错误的数据。

Hmmm, this seems like it could be a horrible security hole as well, depending on where the data is coming from.嗯,这似乎也可能是一个可怕的安全漏洞,具体取决于数据的来源。

通过删除所有回车符来清理变量:

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

Using bash :使用bash

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

(Note that the control character in this question is a 'newline' ( \n ), not a carriage return ( \r ); the latter would have output REBOOT| on a single line.) (请注意,此问题中的控制字符是“换行符”( \n ),而不是回车符( \r );后者将在一行上输出REBOOT| 。)

Explanation解释

Uses the Bash Shell Parameter Expansion ${parameter/pattern/string} :使用 Bash Shell 参数扩展${parameter/pattern/string}

The pattern is expanded to produce a pattern just as in filename expansion.模式被扩展以产生一个模式,就像在文件名扩展中一样。 Parameter is expanded and the longest match of pattern against its value is replaced with string .参数被扩展,模式与其值的最长匹配被替换为字符串 [...] If string is null, matches of pattern are deleted and the / following pattern may be omitted. [...] 如果string为 null,则删除模式匹配项,并且可以省略/后面的模式

Also uses the $'' ANSI-C quoting construct to specify a newline as $'\n' .还使用$'' ANSI-C 引用结构将换行符指定为$'\n' Using a newline directly would work as well, though less pretty:直接使用换行符也可以,虽然不那么漂亮:

echo "|${COMMAND/
}|"

Full example完整示例

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

Or, using newlines:或者,使用换行符:

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

What worked for me was echo $testVar | tr "\n" " "对我有用的是echo $testVar | tr "\n" " " echo $testVar | tr "\n" " "

Where testVar contained my variable/script-output其中 testVar 包含我的变量/脚本输出

Adding answer to show example of stripping multiple characters including \r using tr and using sed.添加答案以显示剥离多个字符的示例,包括使用 tr 和使用 sed 的 \r。 And illustrating using hexdump.并说明使用 hexdump。

In my case I had found that a command ending with awk print of the last item |awk '{print $2}' in the line included a carriage-return \r as well as quotes.就我而言,我发现以 awk print 结尾的命令最后一项|awk '{print $2}'在该行中包含一个回车符 \r 以及引号。

I used sed 's/["\n\r]//g' to strip both the carriage-return and quotes.我用sed 's/["\n\r]//g'去掉了回车和引号。

I could also have used tr -d '"\r\n' .我也可以使用tr -d '"\r\n'

Interesting to note sed -z is needed if one wishes to remove \n line-feed chars.有趣的是,如果希望删除 \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   |

And this is relevant: What are carriage return, linefeed, and form feed?这很重要: 什么是回车、换行和换页?

  • CR == \r == 0x0d CR == \r == 0x0d
  • LF == \n == 0x0a LF == \n == 0x0a

If you are using bash with the extglob option enabled, you can remove just the trailing whitespace via:如果您在启用 extglob 选项的情况下使用 bash,则可以通过以下方式仅删除尾随空格:

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

This outputs:这输出:

|
RE BOOT|

Or replace %% with ## to replace just the leading whitespace.或者将 %% 替换为 ## 以仅替换前导空格。

You can simply use echo -n "|$COMMAND|"您可以简单地使用echo -n "|$COMMAND|" . .

$ man echo

-n do not output the trailing newline -n不输出尾随换行符

To address one possible root of the actual issue, there is a chance you are sourcing a crlf file.为了解决实际问题的一个可能根源,您可能正在采购一个 crlf 文件。

CRLF Example: CRLF 示例:

.env (crlf) .env (crlf)

VARIABLE_A="abc"
VARIABLE_B="def"

run.sh运行.sh

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

Returns:回报:

abc
def
 def

If however you convert to LF:但是,如果您转换为 LF:

.env (lf) .env (lf)

VARIABLE_A="abc"
VARIABLE_B="def"

run.sh运行.sh

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

Returns:回报:

abc
def
abc def

Short answers are the best (please upwote) Use this bashism if you don't want spawn processes like (tr, sed or awk) for such a simple task, bash can do that alone:简短的答案是最好的(请upwote)如果您不希望像(tr,sed或awk)这样的简单任务产生过程,请使用此bashism,bash可以单独完成:

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

From the Documentation:从文档:

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

Thanks for upwoting.感谢您的支持。 This is the best answer.这是最好的答案。

Grep can be used to filter out any blank lines. Grep 可用于过滤掉任何空行。 This is useful if you have several lines of data and want to remove any empty.如果您有几行数据并且想要删除任何空白,这将很有用。

echo "$COMMAND" | grep .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM