单引号和$ in string bash

时间:2015-05-08 18:48:01

标签: bash

我运行下面的脚本来对函数中的文件路径运行一些检查 一些路径包含单引号,临时文件包含" $" 如果我将变量括在单引号(下面的名称变量)中,那么如果有一个'则将字符串截断。在文件路径中。如果我在文件路径周围使用双引号,那么如果有" $"则会截断。在路上。 这个循环难题有什么办法吗?

File=/root/fed/~$reader.txt

回显就好像文件路径中有$

/root/fed/eager.txt

如果有'在文件路径中,我附上单引号(以阻止上述发生)然后

File='/root/fed/reader's'
(this wont echo)

代码是:

find / -type f -print0 | xargs -0 -I name bash -c "fnchash 'name'" 

fnchash () {
    echo "$1"
}

3 个答案:

答案 0 :(得分:6)

单引号字符串可能不包含单引号。甚至没有逃脱它们。不带引号或双引号和未转义的$引入了一个变量引用,它扩展为引用的shell变量的值,如果没有定义这样的变量,则引入任何内容。

一种解决方案涉及双引号和转义字符。例如:

File=/root/fed/~\$reader.txt
File=/root/fed/reader\'s
File="/root/fed/\$reader's.txt"

另请注意,引号不一定是 string 分隔符 - 它们是 sub 字符串分隔符。因此,这些工作也是如此:

File=/root/fed/~'$'reader.txt
File=/root/fed/reader"'"s

如果您需要在运行时自动引用读取的数据,那么您还应该了解bash的内置printf命令(这比命令更有用)一个独立的命令)。请特别注意,%q字段描述符对其参数执行所有必需的引用,以使它们可以作为shell输入重用。

printf '%q' $File

答案 1 :(得分:2)

摆脱这个难题的方法是停止尝试将数据视为代码。此代码段将文件名作为数据(参数)传递,而不是尝试将它们注入代码字符串,从而完全防止这些问题:

$ cat myscript 
fnchash () {
    for arg
    do
      printf "Now processing: %s\n" "$arg"
    done
}
export -f fnchash

find . -type f -exec bash -c 'fnchash "$@"' _ {} +

$ ls -1
File with space and '.txt
myscript
some file.txt

$ bash myscript 
Now processing: ./some file.txt
Now processing: ./myscript
Now processing: ./File with space and '.txt

这使用以下事实:您可以使用位置参数bash -c 'command' argv0 argv1 argv2..'command'$0调用$1来运行$2。设置为传递的参数打击并处理它们就好像它们是脚本的参数(-c下的man bash)。

然后使用

-exec bash -c 'command' _ {} +运行command$0设置为虚拟值_,其余参数设置为find找到的文件名(-exec下的man find)。

bash命令可以像任何脚本一样处理这些参数。

同样的技术也可以与xargs一起使用,这里以5个方式并行处理20个文件的块:

find . -type f -print0 | xargs -0 -P 5 -n 20 bash -c 'fnchash "$@"' _

答案 2 :(得分:0)

您可以使用单引号并将所有单引号替换为转义符号来解决此问题, 要么 使用双引号并将所有$替换为已转义的。