只有那些外界的报价空间分割字符串 [英] Split a string only by spaces that are outside quotes

查看:95
本文介绍了只有那些外界的报价空间分割字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,这被问得bilion次,但我又没有找到我的具体情况下的最佳解决方案。

I know, this was asked a bilion times, but i yet did not find the optimal solution for my specific case.

我receving的字符串是这样的:

I'm receving a string like this:

VAR1="some text here" VAR2='some another text' some script --with --some=args

如何分割这样的字符串:(纯bash中最preferable)

how do i split the string like this: (most preferable in pure bash)

VAR1="some text here"
VAR2='some another text'
some script --with --some=args

设置 - $ STR 导致 VAR1 =一些

设置 - $海峡返回整个字符串

评估设置 - $海峡结果 VAR1 =一些文字在这里

当然,我可以报价添加到由评估返回的字符串,但我得到高度不信任的输入,所以评估是不是所有一个选项。

sure, i could add quotes to the string returned by eval, but i get highly untrusted input so eval is not a option at all.

重要提示:有可能从零到无限的增值经销商,他们可以是单或双引号

Important: there can be from zero to unlimited VARs and they can be single or double quoted

此外, VAR 是一个假名字在这里,它其实可以是任何东西。

Also, the VAR is a fake name here, it can in fact be anything.

感谢。

推荐答案

呵,看来我迟到了:)

下面是如何我处理环境瓦尔脚本之前通过。

Here is how i'm dealing with environment vars passed before script.

首先关闭所有, escape_args 功能将难逃空间内通过增值分销商,

First off all, escape_args function will escape spaces "inside" passed vars,

因此​​,如果用户通 VAR =富巴,它将成为 VAR = foo的\\ 0040bar ​​

so if user pass VAR="foo bar", it will become VAR=foo\0040bar.

function escape_args {
  local str=''
  local opt=''
  for c in $1; do
    if [[ "$c" =~ ^[[:alnum:]]+=[\"|\'] ]]; then
      if [[ "${c: -1}" =~ [\"|\']  ]]; then
        str="$str $( echo $c | xargs )"
      else
        # first opt chunk
        # entering collector
        opt="$c"
      fi
    else
      if [ -z "$opt" ]; then
        # not inside collector
        str="$str $c"
      else
        # inside collector
        if [[ "${c: -1}" =~ [\"|\']  ]]; then
          # last opt chunk
          # adding collected chunks and this last one to str
          str="$str $( echo "$opt\0040$c" | xargs )"
          # leaving collector
          opt=''
        else
          # middle opt chunk
          opt="$opt\0040$c"
        fi
      fi
    fi
  done
  echo "$str"
}

让测试对你输入的修改版本:

Lets test it against a modified version of your input:

s="VAR1=\"some text here\" VAR2='some another text' VAR3=\"noSpaces\" VAR4='noSpacesToo' VAR5=noSpacesNoQuotes some script --with --some=args"

echo $(escape_args "$s")

VAR1=some\0040text\0040here VAR2=some\0040another\0040text VAR3=noSpaces VAR4=noSpacesToo VAR5=noSpacesNoQuotes some script --with --some=args

看到的,瓦尔是空间转义和引用删除,因此声明将正常工作。

现在你可以通过你输入的部分进行迭代。

Now you can iterate through the parts of your input.

下面是一个例子,你如何声明VAR和运行脚本:

Here is an example how you can declare vars and run the script:

cmd=''
for c in $(escape_args "$s"); do
  [[ "$c" =~ ^[[:alnum:]]+= ]] && declare "$(echo -e $c)" && continue
  cmd="$cmd $c"
done

echo VAR1 is set to $VAR1
echo VAR2 is set to $VAR2
echo VAR3 is set to $VAR3
echo VAR4 is set to $VAR4
echo VAR5 is set to $VAR5
echo $cmd

这迭代器做两个简单的:

This iterator is doing two simple things:


  • 声明一个VAR如果块匹配 SOME_VAR = 前pression

  • 添加块到最后的CMD否则

  • declaring a var if the chunk matching SOME_VAR= expression
  • adding the chunk to the final cmd otherwise

所以输出将是:

VAR1 is set to some text here
VAR2 is set to some another text
VAR3 is set to noSpaces
VAR4 is set to noSpacesToo
VAR5 is set to noSpacesNoQuotes
some script --with --some=args

这是贴近您的需求?

Is this close to your needs?

这篇关于只有那些外界的报价空间分割字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆