为什么检测到通配符时命令无法正常工作

为什么检测到通配符时命令无法正常工作

shell 脚本中的代码段

 fname=$(sed 's/(.*//' <<< $p | awk '{ print $NF }')  
 if [[ $fname == *['!'@#\$%^\&*()_+]* ]]
 then
   flag1=0
 fi

其中 $p 是文本文件中的一行。

p 值为 >= (short)BigBlock * DISK_SIZE + Size)

当对 p 值执行上述 shell 脚本时,它会给出垃圾结果,例如出现在终端上

>= (short)BigBlock  file1 file2 file3 DISK_SIZE + Size)

其中 file1 file2 file3 是文件夹中的文件

我的猜测是 * 被视为 ls 命令

可能的解决方案是什么

答案1

摘要: 您echo $p的代码中可能有这样的地方。您需要双引号$p


不,*不被视为ls命令。然而,由于在某处不加引号地使用(不在问题中显示的代码中),它被视为文件名通配模式

在分配和使用 的值时需要小心,p并使用适当的引号来保护字符串。

文件名通配模式不会在此处字符串中扩展:

$ cat <<< *
*

$p因此,在调用中使用不带引号的 没有任何问题sed。然而,显式引用变量扩展几乎总是更好。另请参阅$fname测试中未引用的使用。这肯定应该加双引号。

你说脚本输出文本

>= (short)BigBlock  file1 file2 file3 DISK_SIZE + Size)

没有什么会引起该字符串在问题中显示的脚本中输出。这可能是由于你做的

echo $p

脚本中的其他地方。

再次,在 周围使用双引号$p

echo "$p"

这样,您就可以阻止 shell 对其值执行文件名通配(扩展*)。

一般来说,echo仅用于静态字符串,用于printf可变数据:

printf '$p is "%s"\n' "$p"

与最后一点相关:为什么 printf 比 echo 更好?

答案2

首先,在等待真正的 $p 值字符串时:确保引用 $p。

fname=$(sed 's/(.*//' <<< "$p" | awk '{ print $NF }') 

另请注意,sed 's/(.*//'将匹配字符串的末尾。

f='(something) and more stuff';sed 's/(.*//' <<< "$f"

结果当然是空字符串。

f='(something)-and more stuff';sed 's/([^)]*)//' <<< "$f"

结果: - 以及更多内容

相关内容