保留字符串中的空格作为命令行参数

时间:2009-10-12 11:59:50

标签: bash scripting whitespace

我在这里面临一个小问题,我想将包含空格的字符串传递给另一个程序,以便将整个字符串视为命令行参数。

简而言之,我想通过bash shell脚本执行以下结构的命令: command_name -a arg1 -b arg2 -c“arg with whitespaces here”

但无论我如何尝试,空格都不会保留在字符串中,默认情况下会被标记化。请解决方案,

编辑:这是我脚本的主要部分:

#!/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 ---------#

6 个答案:

答案 0 :(得分:5)

您遇到此问题是因为您将命令存储在变量中,然后再将其展开;除非有充分理由这样做,否则

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有一个good page on the subject。在我看来,最有用的是将命令放在数组而不是简单的变量中:

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

这避免了空格分隔单词和单词空间之间的整体混淆,因为单词不是用空格分隔的 - 它们位于数组的单独元素中。使用[@]后缀以双引号扩展数组会保留该结构。

(BTW,另一种选择是使用转义引号,而不是像你正在做的那样,然后用eval运行命令。不要这样做;这是引入奇怪的解析错误的好方法。)< / p>

答案 1 :(得分:2)

我有一个建议:

# 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

答案 2 :(得分:1)

可能你需要用双引号括起参数(例如“$ {6}”)。

OP评论之后应该是“$ BLACKRAY_END_POINT”

答案 3 :(得分:1)

修改

尝试:

BLACKRAY_END_POINT="'default -p 8890'"

BLACKRAY_END_POINT='"default -p 8890"'

BLACKRAY_END_POINT="default\ -p\ 8890"

BLACKRAY_END_POINT='default\ -p\ 8890'

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 two words
2 two        words
3 two
4 words

一个名为“spacetest”的脚本:

#!/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

使用./spacetest "two--------words"运行它(用空格替换连字符):

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

您可以看到,在“无引号”部分,它尝试执行grep two words test.txt除了“test.txt”之外还将“单词”解释为文件名。此外,echo删除了额外的空格。

当引用参数时,如第二部分所述,grep将其视为一个参数(包括额外的空格)并正确处理。 echo保留了额外的空格。

顺便说一下,我使用额外的空间来帮助演示。

答案 4 :(得分:0)

以下是我通过 exec su USER exec su - USER 重新启动脚本的示例。它适用于:

  • 从相对路径或当前工作目录中调用
  • 脚本名称和参数中的空格
  • 参数中的单引号和双引号,没有疯狂的转义,如:\\&#34;

#
# 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

答案 5 :(得分:-1)

其他博客上的帖子为我解决了这个空白问题:http://logbuffer.wordpress.com/2010/09/23/bash-scripting-preserve-whitespaces-in-variables/

默认情况下,空格是:

bash> VAR1="abc        def    gh ijk"
bash> echo $VAR1
abc def gh ijk
bash>

&#34;此行为的原因是内部shell变量 $ IFS(内部字段分隔符),默认为空格,制表符和换行符。 要保留所有连续的空格,您必须将IFS设置为不同的&#34;

IFS 绕过:

bash> IFS='%'
bash> echo $VAR1
abc        def    gh ijk
bash>unset IFS
bash>

对我的命令案例非常有效:

su - user1 -c 'test -r "'${filepath}'"; ....'

希望这有帮助。