nic*_*kl- 7 arrays string bash arguments argument-passing
在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变量填充为数组.
#!/usr/bin/env bash
#string2arry
args=()
function inspect() {
  local inspct=$(declare -p args)
  inspct=${inspct//\[/\\n\\t[}; 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.\""
一旦检测到开引号,就用组合词填充变量,并且仅在闭引号到达后才将其附加到数组。
#solution2
j=''
for a in ${1}; do
  if [ -n "$j" ]; then
    [[ $a =~ ^(.*)[\"\']$ ]] && {
      args+=("$j ${BASH_REMATCH[1]}")
      j=''
    } || j+=" $a"
  elif [[ $a =~ ^[\"\'](.*)$ ]]; then
    j=${BASH_REMATCH[1]}
  else
    args+=($a)
  fi
done
$ ./test_string2array solution2
1. Testing single args
$ echo "arg1 arg2 arg3 arg4 arg5" | ./string2array solution2
args=(
    [0]="arg1"
    [1]="arg2"
    [2]="arg3"
    [3]="arg4"
    [4]="arg5"
)
Result : PASSED!
2. Testing multi args " quoted
$ echo 'arg1 "multi arg 2" arg3 "a r g 4" arg5' | ./string2array solution2
args=(
    [0]="arg1"
    [1]="multi arg 2"
    [2]="arg3"
    [3]="a r g 4"
    [4]="arg5"
)
Result : PASSED!
3 Testing multi args ' quoted
$ echo "arg1 'multi arg 2' arg3 'a r g 4' arg5" | ./string2array solution2
args=(
    [0]="arg1"
    [1]="multi arg 2"
    [2]="arg3"
    [3]="a r g 4"
    [4]="arg5"
)
Result : PASSED!
| 归档时间: | 
 | 
| 查看次数: | 2509 次 | 
| 最近记录: |