用下划线连接两个变量


54

我需要连接两个变量来创建具有下划线的文件名。让我们调用变量,$FILENAME$EXTENSION从文件中读取文件名。

FILENAME=Hello
EXTENSION=WORLD.txt

现在...

我尝试了以下操作,但未成功:

NAME=${FILENAME}_$EXTENSION
NAME=${FILENAME}'_'$EXTENSION
NAME=$FILENAME\\_$EXTENSION

我总是得到某种奇怪的输出。通常下划线优先。

我需要它

echo $NAME
Hello_WORLD.txt

2
您的脚本可能包含回车符。
斯特凡Chazelas

是的,就是这样。:D
Rhyuk

Answers:


66

您可以使用如下形式:

NAME=$(echo ${FILENAME}_${EXTENSION})

这也可以:

NAME=${FILENAME}_${EXTENSION}

1
问题是我从中读取名称的文件。Windows格式化...之后,您的解决方案效果很好。谢谢
Rhyuk

2
第一条命令会破坏变量的值和命令替换的使用,echo因此可能无济于事。问题中已经给出了第二个命令。
吉尔斯(Gilles)'所以

1
是! 我喜欢它。最长的时间让我很烦。感谢您的解决方案!
racl101

这对我有用。当我使用“ $ FILENAME_ $ EXTENSION”时,仅显示“ $ EXTENSION”的值。您能帮忙解释一下为什么会这样吗?谢谢
雷浩

12

你的:

NAME=${FILENAME}_$EXTENSION
NAME=${FILENAME}'_'$EXTENSION

都很好,所以将是:

NAME=${FILENAME}_${EXTENSION}
NAME=$FILENAME'_'$EXTENSION
NAME=$FILENAME\_$EXTENSION
NAME=$FILENAME"_$EXTENSION"

(但肯定不是 NAME=$(echo ${FILENAME}_${EXTENSION})因为它使用echosplit+glob运营商)。

NAME=$FILENAME_$EXTENSION

将与以下相同:

NAME=${FILENAME_}${EXTENSION}

因为_(与\或相反')是变量名称中的有效字符。

您的问题是您用CRLF而不是LF分隔行,这意味着这些可变内容以CR字符结尾。

当CR字符写入终端时,它告诉终端将光标移动到行首。因此,Hello<CR>_WORLD.TXT<CR>当发送到终端时将显示为_WORLD.TXT(覆盖Hello)。


1

我已改用上述${FILENAME}_${EXTENSION}语法。

我曾经$()在需要用下划线连接两个变量时使用。例如,$YYYYMMDD$()_$HHMMSS要生成一个包含时间戳的文件名,格式为YYYYMMDD_HHMMSS。中间$()什么也不返回,并且将两个变量分开。

我曾经time使用该$YYYYMMDD$()_$HHMMSS方法以及上面的一些方法来评估分配,并且在我使用此方法的旧服务器上,它们都报告了0ms。性能似乎不是问题。


那没有回答问题。您应该为此提出一个新问题。$()确实将子shell分叉到一些shell中(有些将其优化了)。它也劫持了一个运营商,因为它不是为特定目的而设计的。${x}_y是你想要的。
斯特凡Chazelas

您是什么意思,“那不能回答问题。”?这不是一个很好的答案,但这是一个答案。
斯科特,

编辑以消除歧义。
user208145 '17

0

您应该使用小写字母的变量(这是最佳做法)。
因此,我将使用文件名和扩展名而不是FILENAME和EXTENSION

当您说“从文件读取文件名”时,我假设脚本是:

read -r filename  <file.txt
extension=World.txt

并且您想用下划线连接变量$ filename和$ extension _
您提供的示例(除了:no double \)在这里可以正常工作:

name=${filename}_$extension
name=${filename}'_'$extension
name=$filename\_$extension

和其他一些一样:

name="${filename}"'_'"${extension}"
name="$filename"'_'"$extension"
name="${filename}_${extension}"

因此,您的问题不在于变量如何组合在一起,而在于变量的内容。认为这似乎是合理的:

read -r filename  <file.txt

\r如果从Windows文件读取,将读取尾随回车符。

一种简单的解决方案(针对ksh,bash,zsh)是从读取变量中删除所有控制字符:

filename=${filename//[[:cntrl:]]/}

可以使用一个带有回车符的值来模拟:

$ filename=$'Hello\r'
$ echo "starting<$filename>end"
>endting<Hello                       ### note the return to the start of line.
$ echo "starting<${filename//[[:cntrl:]]/}>end"
starting<Hello>end

或者,替换为filename

$ filename="${filename//[[:cntrl:]]/}"
$ echo "start<$filename>end"
start<Hello>end

结论。

所以这:

name="${filename//[[:cntrl:]]/}_${extension//[[:cntrl:]]/}"

name即使其他变量包含控制字符,也将获得正确的值。



-2

您也可以使用此方法:用空格分隔单独的var,然后使用tr串联它们以删除空格。

TableNameToCreate="MyTable"
# concatenation work is done here 
$(echo "$TableNameToCreate _my_other_Info " | tr -d " ")

#Proof
echo "Var to create with var pasted as prefix to suffix
    $(echo "$TableNameToCreate _my_other_Info " | tr -d " ") 
. "

# create a new var
NewVar=$(echo "$TableNameToCreate _my_other_Info " | tr -d " ")

#proof
echo "$NewVar"

(1)这个问题已经得到了足够的答案。(2)如果现有变量中包含特殊字符,您的答案是什么?
G-Man

这不能解决包含回车符的变量的问题。它还会删除不需要的空格。
库萨兰达

@Kusalananda:实际上,除非我忽略了某些东西,否则这可以处理回车;空间是唯一的问题。
G-Man
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.