Preserving whitespaces in a string as a command line argument
我在这里面临一个小问题,我想将一个包含空格的字符串传递给另一个程序,以便将整个字符串视为命令行参数。
简而言之,我想通过bash shell脚本执行以下结构的命令:
command_name -a arg1 -b arg2 -c"此处带有空格的arg"
但是无论如何尝试,空格都不会保留在字符串中,并且默认情况下会被标记化。 请解决
编辑:这是我脚本的主要部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/bin/bash #-------- BLACKRAY CONFIG ---------------# # Make sure the current user is in the sudoers list # Running all instances with sudo BLACKRAY_BIN_PATH='/opt/blackray/bin' BLACKRAY_LOADER_DEF_PATH='/home/crozzfire' BLACKRAY_LOADER_DEF_NAME='load.xml' BLACKRAY_CSV_PATH='/home/crozzfire' BLACKRAY_END_POINT='default -p 8890' OUT_FILE='/tmp/out.log' echo"The current binary path is $BLACKRAY_BIN_PATH" # Starting the blackray 0.9.0 server sudo"$BLACKRAY_BIN_PATH/blackray_start" # Starting the blackray loader utility BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e""$BLACKRAY_END_POINT""" sudo time $BLACKRAY_INDEX_CMD -a $OUT_FILE #--------- END BLACKRAY CONFIG ---------# |
之所以遇到这个问题,是因为您将命令存储在变量中,然后再将其展开。除非有充分的理由这样做,否则不要:
1 | sudo time $BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e"$BLACKRAY_END_POINT" -a $OUT_FILE |
如果确实需要存储命令并在以后使用它,则有几个选项;例如, bash-hackers.org Wiki上有一个很好的主题页面。在我看来,这里最有用的方法是将命令放入数组而不是简单的变量中:
1 2 3 | BLACKRAY_INDEX_CMD=($BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e"$BLACKRAY_END_POINT") sudo time"${BLACKRAY_INDEX_CMD[@]}" -a $OUT_FILE |
这样可以避免空格分隔的单词和空格内的单词之间的整体混乱,因为单词不是由空格分隔的-它们位于数组的单独元素中。使用后缀
(顺便说一句,另一种选择是使用转义引号,就像您正在做的那样,然后使用
我有一个建议:
1 2 3 4 5 6 7 8 | # iterate through the passed arguments, save them to new properly quoted ARGS string while [ -n"$1" ]; do ARGS="$ARGS '$1'" shift done # invoke the command with properly quoted arguments my_command $ARGS |
编辑:
尝试:
1 | BLACKRAY_END_POINT="'default -p 8890'" |
要么
1 | BLACKRAY_END_POINT='"default -p 8890"' |
要么
1 | BLACKRAY_END_POINT="default\ -p\ 8890" |
要么
1 | BLACKRAY_END_POINT='default\ -p\ 8890' |
和
1 | BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e $BLACKRAY_END_POINT" |
原始答案:
blackray_loader是shell脚本吗?
这是一个说明,您在指定参数和处理参数时都必须处理此问题:
名为" test.txt"的文本文件(包括行号):
1 2 3 4 | 1 two words 2 two words 3 two 4 words |
一个名为" spacetest"的脚本:
1 2 3 4 5 6 7 8 9 10 | #!/bin/bash echo"No quotes in script" echo $1 grep $1 test.txt echo echo"With quotes in script" echo"$1" grep"$1" test.txt echo |
用
1 2 3 4 5 6 7 8 9 10 | No quotes in script two words grep: words: No such file or directory test.txt:1 two words test.txt:2 two words test.txt:3 two With quotes in script two words 2 two words |
您可以看到,在"无引号"部分中,它尝试执行
如第二节所述,将参数加引号时,
顺便说一下,我使用了多余的空间只是为了帮助演示。
可能需要用双引号将参数引起来(例如" $ {6}")。
在OP评论后应为" $ BLACKRAY_END_POINT"
以下是我通过exec su USER或exec su-USER重新启动脚本的示例。它可以容纳:
- 从相对路径或当前工作目录中调用
- 脚本名称和参数中的空格
- 参数中的单引号和双引号,没有疯狂的转义,例如:
1 2 3 4 5 6 7 8 | # # This script should always be run-as a specific user # user=jimbob if [ $(whoami) !="$user" ]; then exec su -c"'$(readlink -f"$0")' $(printf" %q""$@")" - $user exit $? fi |
其他博客上的帖子为我解决了这个空白问题:http://logbuffer.wordpress.com/2010/09/23/bash-scripting-preserve-whiteserve-in-variables/
默认情况下,空格被修剪:
1 2 3 4 | bash> VAR1="abc def gh ijk" bash> echo $VAR1 abc def gh ijk bash> |
"造成这种现象的原因是内部外壳变量$ IFS(内部字段分隔符),默认为空格,制表符和换行符。
要保留所有连续的空格,您必须将IFS设置为其他值"
使用IFS旁路:
1 2 3 4 5 | bash> IFS='%' bash> echo $VAR1 abc def gh ijk bash>unset IFS bash> |
对于我的命令情况,它的工作非常出色:
1 | su - user1 -c 'test -r"'${filepath}'"; ....' |
希望这可以帮助。