单词指向数组

问题:

在bash脚本中,将包含多个单词的文字引号的字符串转换为具有相同分析参数结果的数组的最佳方式是什么?

争议:

存在许多问题,都采用回避策略来避免问题,而不是找到解决方案,这个问题引发了以下争论,并希望鼓励读者关注争论,如果您有所准备,参与挑战以找到最佳解。

提出的论点:

  • 尽管有很多情况应避免使用这种模式,因为存在更好的替代解决方案,作者认为仍然存在有效的使用案例。 这个问题将试图产生一个这样的使用案例,但不要求其可行性只是它可能出现在真实世界中的可能情况。
  • 您必须找到满足要求的最佳解决方案。 该用例是专门针对其真实世界的应用程序而选择的。 您可能不同意所作出的决定,但不负责仅仅提供解决方案的意见。
  • 在不改变输入或选择运输的情况下满足要求。 两者都是通过真实世界的场景进行特别选择,以捍卫这些部分超出你的控制范围的叙述。
  • 这个问题没有答案,这个问题旨在解决这个问题。 如果你倾向于避免这种模式,那么就简单地避免这个问题,但如果你认为你面临的挑战,让我们看看你将如何解决这个问题。
  • 有效用例:

    将当前正在使用的现有脚本转换为通过命名管道或类似流接收参数。 为了最大限度地减少开发者控制之外的无数脚本的影响,决定不改变界面。 现有的脚本必须能够像以前一样通过新的流实现传递相同的参数。

    现有实施:

    $ ./string2array arg1 arg2 arg3
    args=(
        [0]="arg1"
        [1]="arg2"
        [2]="arg3"
    )
    

    所需更改:

    $ echo "arg1 arg2 arg3" | ./string2array
    args=(
        [0]="arg1"
        [1]="arg2"
        [2]="arg3"
    )
    

    问题:

    正如Bash和Double-Quotes指出的那样,传递给argv文字的引号不会像预期的那样被解析。

    该工作台脚本可用于测试各种解决方案,处理运输并制定可衡量的响应。 建议您专注于以字符串作为参数来源的解决方案脚本,并且应该将$ args变量作为数组填充。

    string2array工作台脚本:

    #!/usr/bin/env bash
    #string2arry
    
    args=()
    
    function inspect() {
      local inspct=$(declare -p args)
      inspct=${inspct//[/nt[}; inspct=${inspct//'/}; inspct="${inspct:0:-1}n)"
      echo -e ${inspct#*-a }
    }
    
    while read -r; do
      # source the solution to turn $REPLY in $args array
      source $1 "${REPLY}"
      inspect
    done
    

    标准解决方案 - 失败

    将字符串转换为空格分隔的单词数组的解决方案适用于上面的第一个示例:

    #solution1
    
    args=($@)
    

    不想要的结果

    不幸的是,标准解决方案对引用的多字参数产生了不希望的结果:

    $ echo 'arg1 "multi arg 2" arg3' | ./string2array solution1
    args=(
        [0]="arg1"
        [1]=""multi"
        [2]="arg"
        [3]="2""
        [4]="arg3"
    )
    

    挑战:

    使用工作台脚本提供了一个解决方案片段,它将为接收到的参数产生以下结果。

    预期结果:

    $ echo 'arg1 "multi arg 2" arg3' | ./string2array solution-xyz
    args=(
        [0]="arg1"
        [1]="multi arg 2"
        [2]="arg3"
    )
    

    解决方案应该与各种标准参数解析兼容。 以下单元测试应通过所提供的解决方案。 如果你能想到当前单元测试中缺少的任何内容,请留下评论,我们可以更新它。

    单元测试的要求

    更新:测试简化并包含Johnathan Leffer测试

    #!/usr/bin/env bash
    #test_string2array
    solution=$1
    function test() {
      cmd="echo "${1}" | ./string2array $solution"
      echo "$ ${cmd}"
      echo ${1} | ./string2array $solution > /tmp/t
      cat /tmp/t
      echo -n "Result : "
      [[ $(cat /tmp/t|wc -l) -eq 7 ]] && echo "PASSED!" || echo "FAILED!"
    }
    
    echo 1. Testing single args
    test 'arg1 arg2 arg3 arg4 arg5'
    echo
    echo 2. Testing multi args " quoted
    test 'arg1 "multi arg 2" arg3 "a r g 4" arg5'
    echo
    echo 3 Testing multi args ' quoted
    test "arg1 'multi arg 2' arg3 'a r g 4' arg5"
    echo
    echo 4 Johnathan Leffer test
    test "He said, "Don't do that!" but "they didn't listen.""
    

    内置的declare似乎正在做你想要的; 在我的测试中,这是您的inspect功能,似乎不适合正确测试所有输入:

    # solution3
    declare -a "args=($1)"
    

    然后

    $ echo "arg1 'arg2a arg2b' arg3" | while read -r; do
    >  source solution3 "${REPLY}"
    >  for arg in "${args[@]}"; do
    >   echo "Arg $((++i)): $arg"
    >  done
    > done
    Arg 1: arg1
    Arg 2: arg2a arg2b
    Arg 3: arg3
    

    所以我认为xargs实际上适用于所有的测试用例,例如:

    echo 'arg1 "multi arg 2" arg3' | xargs -0 ./string2array
    

    第二次尝试

    在不需要额外变量的情况下追加元素。

    #solution3
    for i in $1; do
      [[ $i =~ ^["'] ]] && args+=(' ')
      lst=$(( ${#args[@]}-1 ))
      [[ "${args[*]}" =~ [[:space:]]$ ]] && args[$lst]+="${i/["']/} " ||  args+=($i)
      [[ $i =~ ["']$ ]] && args[$lst]=${args[$lst]:1:-1}
    done
    
    链接地址: http://www.djcxy.com/p/78035.html

    上一篇: word args to array

    下一篇: index issue with ng