【发布时间】:2013-10-21 04:05:55
【问题描述】:
我有以下变量。
echo "|$COMMAND|"
返回
|
REBOOT|
如何删除第一个换行符?
【问题讨论】:
我有以下变量。
echo "|$COMMAND|"
返回
|
REBOOT|
如何删除第一个换行符?
【问题讨论】:
为了解决实际问题的一个可能根源,您可能会采购一个 crlf 文件。
CRLF 示例:
.env (crlf)
VARIABLE_A="abc"
VARIABLE_B="def"
运行.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"
运行.sh
#!/bin/bash
source .env
echo "$VARIABLE_A"
echo "$VARIABLE_B"
echo "$VARIABLE_A $VARIABLE_B"
返回:
abc
def
abc def
【讨论】:
tr 命令可以替换为// bashism:
COMMAND=$'\nREBOOT\r \n'
echo "|${COMMAND}|"
|
OOT
|
echo "|${COMMAND//[$'\t\r\n']}|"
|REBOOT |
echo "|${COMMAND//[$'\t\r\n ']}|"
|REBOOT|
请参阅 bash 手册页中的 Parameter Expansion 和 QUOTING:
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|
注意:bash 必须启用 extglob 选项 (shopt -s extglob) 才能使用 *(...) 语法。
【讨论】:
COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n ']}|" 返回|REBOOT|
\n 之后鞭打空格以防止这种情况:COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n']}|" 将返回|RE BOOT|。
${COMMAND//[$'\t\r\n']} 中的模式如何工作?我以为${COMMAND//[\t\r\n]} 会简单地工作,但事实并非如此。 $ 符号和单引号是什么?
添加答案以显示剥离多个字符的示例,包括使用 tr 和使用 sed 的 \r。 并说明使用 hexdump。
在我的例子中,我发现行中最后一项 |awk '{print $2}' 的 awk print 结尾的命令包括回车符 \r 和引号。
我用sed 's/["\n\r]//g' 去掉了回车和引号。
我也可以使用tr -d '"\r\n'。
如果想删除 \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 |
这是相关的: What are carriage return, linefeed, and form feed?
【讨论】:
您可以简单地使用echo -n "|$COMMAND|"。
【讨论】:
对我有用的是echo $testVar | tr "\n" " "
testVar 包含我的变量/脚本输出的地方
【讨论】:
使用bash:
echo "|${COMMAND/$'\n'}|"
(请注意,此问题中的控制字符是“换行符”(\n),而不是回车符(\r);后者将在一行上输出REBOOT|。)
使用 Bash Shell Parameter Expansion ${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|
【讨论】:
如果您在启用 extglob 选项的情况下使用 bash,则可以通过以下方式仅删除尾随空格:
shopt -s extglob
COMMAND=$'\nRE BOOT\r \n'
echo "|${COMMAND%%*([$'\t\r\n '])}|"
这个输出:
|
RE BOOT|
或将 %% 替换为 ## 以仅替换前导空格。
【讨论】:
通过删除所有回车符来清理你的变量:
COMMAND=$(echo $COMMAND|tr -d '\n')
【讨论】:
tr -d '\r'吗?
tr。只需COMMAND=$(echo $COMMAND) 就会产生类似的效果。这大概是魔鬼的产生,因为它调用了一个新的过程,但对于人类的眼睛来说,它仍然非常短暂和甜蜜,如果你有一两秒钟的空闲时间,你可能愿意接受这个打击:-)。
${COMMAND//[$'\t\r\n']}
echo "|$COMMAND|"|tr '\n' ' '
将用空格替换换行符(在 POSIX/Unix 中它不是回车)。
说实话,我会考虑从 bash 切换到更理智的东西。或者首先避免生成这种格式错误的数据。
嗯,这似乎也是一个可怕的安全漏洞,具体取决于数据的来源。
【讨论】:
tr -d '\n' dropping 而不是用空格替换
tr '\n' ' ' <<< "|$COMMAND|" 而不是echo ... | ...
"|${COMMAND//$'\n'}|"