Autoconf脚本在使用空格的文件名或路径名时遇到问题。例如,
./configure CPPFLAGS="-I\"/path with space\""
结果为(config.log):
configure:3012: gcc -I"/path with space" conftest.c >&5
gcc: with: No such file or directory
gcc: space": No such file or directory
./configure的编译命令是ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
,我无法修改它(我可以,但是以这种方式解决autoconf不是一般解决方案)。
我认为它归结为获取一个shell变量,该变量包含要解析为单个命令行变量的空格,而不是在空格处拆分。我可以提出的最简单的shell示例是创建一个包含空格的文件,并尝试列出ls
,其中shell变量作为ls
的参数:
$ touch "a b"
$ file="a b"
$ ls $file
ls: a: No such file or directory
ls: b: No such file or directory
这有效,但是非法,因为在autoconf中我无法修改shell代码:
$ ls "$file"
a b
以下所有尝试引用的工作都没有:
$ file="\"a \"b"; ls $file
ls: "a: No such file or directory
ls: b": No such file or directory
$ file="a\ b"
$ file="a\\ b"
$ file="`echo \\"a b\\"`"
等等。
这是不可能在shell脚本中完成的?是否有一个神奇的引用会将带有空格的shell变量扩展为单个命令行参数?
答案 0 :(得分:9)
您应该尝试设置$IFS
环境变量。
来自man bash(1):
IFS - 用于分词的内部字段分隔符 在扩展之后,用read builtin将行分成单词 命令。默认值为''space tab newline''。
例如
IFS=<C-v C-m> # newline
file="a b"
touch $file
ls $file
不要忘记设置$IFS
或发生奇怪的事情。
答案 1 :(得分:4)
如果你发出命令
gcc -I"x y z"
在shell中然后肯定会将单个命令行参数“-Ix y z”传递给gcc。毫无疑问。这就是双引号的全部含义:双引号内的事物不受字段拆分的影响,因此也不受$ IFS的限制。例如。
但是你需要注意你需要的报价数量。例如,如果你说
file="a b" # 1
然后你说
ls $file # 2
所发生的是文件变量的内容是'a b',而不是'“a b”',因为在解析第1行时双引号被“吃掉”。然后将替换后的值按字段分隔,并在两个文件'a'和'b'上获得ls。得到你想要的正确方法是
file="a b"; ls "$file"
现在原始案例中的问题是,当您将变量设置为CONTAINS双引号的字符串时,双引号稍后不会被解释为shell引号符号,而是正常字母。这就是你做
之类的事情的原因 file="\"a b\""; ls $file
实际上,当分析ls命令时,shell将文件变量的内容标记为'“a'和'b”';双引号不再是shell引号字符,而只是变量内容的一部分。如果你设置
,它就类似于 file="\$HOME"; ls $file
您收到'$ HOME'目录不存在的错误 - 没有发生环境变量查找。
所以你最好的选择是
答案 2 :(得分:2)
在Unix世界中使用目录名中的空格只是在寻找麻烦。这不仅仅是在shell脚本中引用的问题(无论如何都需要正确完成):有些工具根本无法处理文件名中的空格。例如,您不能(便携地)编写一个Makefile
规则,该规则说明“baz.o
”中的构建“foo bar/baz.c
”。
如果是CPPFLAGS
,我会按照优先顺序排列:
./configure CC=mygcc
。在这种情况下,mygcc
可能是!/bin/sh
gcc "-I/foo bar/include" "$@"
/tmp/mypath
)并使用CPPFLAGS=-I/tmp/mypath
答案 3 :(得分:1)
您想以下列两种方式引用整个论点:
./configure "CPPFLAGS=-I/path with space"
./configure CPPFLAGS="-I/path with space"
然后./configure
命令会看到一个参数
"CPPFLAGS=-I/path with space"
被解析为名为«CPPFLAGS»
的参数,其值为«-I/path with space»
(为清晰起见,添加了括号)。
答案 4 :(得分:0)
使用引号很有趣。从(轻轻地)阅读bash手册页我认为你必须用\来逃离空间,因此“/ space with space”变成/ path \ with \ space我从未尝试过引号,但似乎它没有一般的工作(你的例子)。转义使用ls而不引用且不更改IFS。
如果使用命令的“转义空格”格式会发生什么?
答案 5 :(得分:0)
$ file="\"a b\""
$ eval ls $file
答案 6 :(得分:0)
一切都取决于变量的使用方式。首先,请注意,如果您使用的是Autoconf,这可能意味着最终将使用make
,因此规则由make
决定,特别是默认的make
规则。即使您可能想要专门使用自己的规则,工具之间的事物必须保持一致,并且某些变量具有标准含义,因此您不希望偏离它们。这不是CPPFLAGS
的情况,但这应该与CFLAGS
类似,这是标准的。请参阅POSIX make
utility,其中变量只是使用标准sh
单词拆分进行扩展,但不提供任何引用机制(字段分隔符由$IFS
控制,但不更改{{ 1}}变量将空格作为普通字符接受,因为这会破坏其他内容,例如能够以标准方式在这些变量中提供多个IFS
和/或-I
选项。
由于-L
存在这样的限制,我认为在Autoconf中试图避免这种限制是没用的。
现在,由于空格必然是字段分隔符,唯一的可能是提供没有空格字符的路径名。如果将来支持路径名中的空格,这可能是通过路径名编码完成的,在高级UI上进行解码(有点像URL)。或者,如果你有选择并且真的想在路径名中使用空格,你可以使用一些非ASCII空间(BTW,这就是RISC OS在路径名中支持空间的方式,强制它是不间断的空间)。 / p>