【问题标题】:Parse string into argument list just like if typed into console?将字符串解析为参数列表,就像输入控制台一样?
【发布时间】:2011-05-23 19:53:08
【问题描述】:

我正在尝试在 10.6 中解析 Xcode 3.2 中的 HEADER_SEARCH_PATHS 环境变量。这是一串路径,例如:

"~/My Path with Spaces" /usr/local /myrootpath

我需要按照 shell 的所有引用规则拆分这个字符串,这样我就可以遍历参数列表并在前面加上 -I,然后像这样将所有这些传递给 gcc:

gcc -I"~/Path with Spaces" -I/usr/local -I/myrootpath

我学过 awk、sed、set、$@,什么都有。我认为这会奏效:

set -- $HEADER_SEARCH_PATHS

for arg in $@  
do  
    echo "arg $i:$arg:" >> mytestfile.txt  
    let "i+=1"  
done  

但它只在空间上分裂,所以结果是:

arg :"~/Path:  
arg 1:with:  
arg 2:Spaces":  
arg 3:/usr/local:  
arg 4:/myrootpath:

我也很好奇是否有一个 gcc 工具可以一步设置包含路径。我一定缺少一些基本的东西。谢谢!

【问题讨论】:

    标签: string list shell split arguments


    【解决方案1】:

    感谢你们的快速反应! 在上面睡觉后,我使用 eval 和 shift 得出了一个解决方案。 诀窍是,如果您访问 $1 它可以工作,但如果您遍历 $* 或 $@ 它会失败。 如果有人知道为什么 $1 shift 方法有效,那么解释可能对其他人有所帮助。 然后我使用 printf 将前置字符串附加到最终字符串。

    #this script will create a prefix.h.gch precompiled
    #header in the project's directory.
    
    cd "${PROJECT_DIR}"
    
    eval set -- $HEADER_SEARCH_PATHS
    
    HEADER_SEARCH_STRING=""  
    while [ $# -gt 0 ]; do  
        HEADER_SEARCH_STRING=HEADER_SEARCH_STRING printf %s "-I\"$1\" "  
        shift  
    done
    
    g++ ${HEADER_SEARCH_STRING} ${OTHER_LINKER_FLAGS} -c ${GCC_PREFIX_HEADER}
    


    #这是对函数做同样事情的另一个例子:

    TESTVAR="\"hello there\" a b /my/path"
    
    TOKENS=""  
    function tokenize {  
        while [ $# -gt 0 ]; do  
            TOKENS=TOKENS printf %s "-I\"$1\" "  
            #TOKENS=TOKENS echo "-I\""$1"\""  
            #echo "$1"  
            shift  
        done  
    }
    
    eval tokenize $TESTVAR
    
    echo $TOKENS
    

    【讨论】:

    • 现在我确切地知道你在寻找什么(不仅仅是一个示例脚本),我更新了我的代码来做你想要的。没有必要使用移位。请看这里stackoverflow.com/questions/4414898/…
    【解决方案2】:
    #!/bin/bash
    
    OTHER_LINKER_FLAGS="-L/usr/lib -lfoo"
    GCC_PREFIX_HEADER="blah"
    HEADER_SEARCH_PATHS="\"/path with spaces\" /usr/include /home/user/includes"
    
    eval set -- $HEADER_SEARCH_PATHS
    
    for arg in "$@"; do
      INCLUDE_STRING+="-I$arg "
    done
    
    g++ ${INCLUDE_STRING} ${OTHER_LINKER_FLAGS} -c ${GCC_PREFIX_HEADER}
    

    【讨论】:

    • 你是说eval set -- ...
    • 在这种特殊情况下,由于他的路径不以“-”开头,因此两者都可以工作。但是,拥有-- 只能提供帮助,所以我添加了它。谢谢你的收获
    • 嘿,谢谢!您的解决方案将我带到了这些页面:stackoverflow.com/questions/1297529/…stevemorin.blogspot.com/2006/04/…,我最终使用 eval 或函数拼凑了一个解决方案,然后在 $1 上使用 shift,我将在下面发布。我是新来的,所以不知道如何给你信用?
    【解决方案3】:

    不漂亮,但是 perl 无处不在...

    $ cat prep.pl 
    #!/usr/bin/perl
    
    while ($#ARGV>=0) {
    print " -I\"";
    print shift;
    print "\"";
    }
    
    $ echo $A
    "a b c" x y
    
    $ perl -e '$cmd="./prep.pl ".$ENV{"A"}; $args= `$cmd`; print("gcc ".$args);'
    gcc  -I"a b c" -I"x" -I"y"
    

    如果你用 system 替换最后一个打印,那么我认为你会得到你想要的(假设你为 gcc 添加了一些东西来实际编译)。

    例如

    $ perl -e '$cmd="./prep.pl ".$ENV{"A"}; $args= `$cmd`; system("gcc ".$args." 1.c");'
    

    可能不是理想的解决方案,但嘿,已经晚了。

    【讨论】:

    • 嗯,我认为您的解决方案会起作用,不幸的是我不知道 perl,并且很难对其进行测试。我是堆栈交换的新手,所以只想打个招呼,感谢您的快速回复,希望您的回答能帮助到达此页面的其他人:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 2010-10-01
    • 2011-04-09
    • 2012-11-11
    相关资源
    最近更新 更多