Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String Bash:像Readline拆分字符串一样拆分字符串_String_Bash_Split_Readline - Fatal编程技术网

String Bash:像Readline拆分字符串一样拆分字符串

String Bash:像Readline拆分字符串一样拆分字符串,string,bash,split,readline,String,Bash,Split,Readline,给定任意Bash“”的字符串表示形式,如何将其拆分为包含其各个“部分”(即命令名和各个参数)的数组,就像shell本身(即Readline)一样在解析它并决定运行哪个可执行文件/函数以及传递哪个参数时,会拆分它吗 我的特定用例需要解析用户定义的别名定义。例如,别名可以定义为: alias c2=“cut-d'-f2”#只是一个例子。。。应该处理任意命令! 下面是我的bash脚本尝试解析它的方式: alias_name=“c2” alias_definition=$(alias-p | gre

给定任意Bash“”的字符串表示形式,如何将其拆分为包含其各个“部分”(即命令名和各个参数)的数组,就像shell本身(即Readline)一样在解析它并决定运行哪个可执行文件/函数以及传递哪个参数时,会拆分它吗


我的特定用例需要解析用户定义的别名定义。例如,别名可以定义为:

alias c2=“cut-d'-f2”#只是一个例子。。。应该处理任意命令!
下面是我的bash脚本尝试解析它的方式:

alias_name=“c2”
alias_definition=$(alias-p | grep“^alias$alias_name=”)#“alias c2='cut-d'\''''''''''-f2'”
alias#u command=${alias#u definition##alias$alias#u name=}}#“'cut-d'\'''''''''''''''''''''''''''''-f2''
alias_命令=$(eval“echo$alias_命令”)#“cut-d'-f2”
alias_parts=($alias_命令)#错误-在每个空格处拆分!
echo“命令名:${alias_parts[0]}”

对于((i=1;i这不是
readline
拆分,而是
getopt
getopts


内置的
集合
可用于拆分字符串

bash$ set -- cut -d ' ' -f2

bash$ echo "'$3'"
' '
编辑:如果要拆分的字符串已经存在于变量中,这就要复杂得多。您可以使用
eval
进行操作,但在这种情况下,我认为这会使事情变得复杂,而不是简化

bash$ a="cut -d ' ' -f2"

bash$ eval set -- $a  # No quoting!

bash$ echo "'$3'"
' '

如果我们将alias_命令的每个参数放在它自己的行上,然后(本地) 设置
IFS=\n
,我们完成了:

parsealias ()
{
   alias_command_spaces=$(eval "echo $(alias $1)" | sed -e "s/alias $1=//") # "cut -d' ' -f2"
   alias_command_nl=$(eval each_arg_on_new_line $alias_command_spaces)      # "cut\n-d' '\n-f2"
   local IFS=$'\n' # split on newlines, not on spaces
   alias_parts=($alias_command_nl) # each line becomes an array element, just what we need
   # now do useful things with alias_parts ....
}
现在,我们只需要在上面使用的
行上编写每个_arg_的命令,例如:

#!/usr/bin/env perl

foreach (@ARGV) {
  s/(\s+)/'$1'/g; # put spaces whithin quotes
  print "$_\n";
}

正如l0b0所说,它不是readline,而是shell本身进行拆分。因此,使用shell本身进行解析

alias c2="cut -d' ' -f2"

split_parts() {
    alias_parts=("$@")
}

alias_defn=$(alias c2)
# 2 evals needed to get rid of quotes
eval eval split_parts ${alias_defn#alias c2=}

for (( i=0; i < ${#alias_parts}; i++ )); do
  echo "parameter $i : \"${alias_parts[$i]}\""
done
请注意,
-d
包含shell实际看到的尾部空间。

要最小化“邪恶的奥托”解决方案:

alias c2="cut -d' ' -f2"
alias_definition=$(alias c2)
eval eval alias_parts=( "${alias_definition#alias c2=}" )
您可以使用“declare-p”进行快速数组打印:

$ declare -p alias_parts
declare -a alias_parts='([0]="cut" [1]="-d " [2]="-f2")'
“printf%q”引用一个参数“以一种可以作为shell输入重用的方式”也很有用(来源:help printf):

弗雷迪·瓦托

不,这不是我的意思。即使没有getopt/getopts,您也可以调用bash脚本,例如
/test.sh a b'c d'
,在脚本中,参数$3将被设置为'c d'。这是我需要的拆分类型,只是我不需要它作为脚本参数,而是手动将其应用于保存在变量中的字符串。这是close是我想要的。但是,除了分割参数外,它似乎还对单个参数执行字符串扩展,因此您得到的不是数组
[cut,-d',,-f2]
(在第三项中删除引号)。是否可以单独执行拆分步骤以保留原始参数?不,我不这么认为。我会有选择地在需要向用户显示的地方添加引号,但它们不是命令的适当部分,它们只用于从shell转义空格等。换句话说,
[cut,-d,-f2]
正是您所需要的…但是,如果您的别名包含例如未引用的通配符,则需要在将其传递给
eval
之前对其进行转义。不幸的是,在我的情况下,
[cut,-d,,-f2]
是我真正需要的,因为我试图在调用预先存在的bash completion函数(特别是为alias'ed命令定义的函数)之前,将各个参数添加到自定义bash completion函数中的COMP_WORDS数组中,我希望将它们添加到数组中,就像如果alias中包含的完整命令直接完成,shell本身将添加它们一样。这恰好没有展开任何字符串或转义,而只是在参数边界处拆分。不,您误解了。引号不是值的一部分,而y是用来防止它被替换的,但是一旦变量中有一个空格,变量的值本身就不(也不应该)包含引号。“正如l0b0所说,它不是readline。”-我认为is是readline,因为下面有一句关于数组的话(恰好包含以这种方式拆分的行)在Bash参考资料中:“该行被拆分为单词,就像Readline拆分它一样”。这是可编程完成的一部分,由Readline完成。shell对命令的解析独立于Readline,更多地基于IFS(正如其他一些海报所指出的).readline只是一个处理行编辑的奇特库。我需要将printf的第二个参数放在引号中,使其像这样工作:
printf%q“${alias_parts[1]}”
Btw,与@tripleee提出的“eval set--”方法相比,该方法是否有明显的优势?
alias c2="cut -d' ' -f2"
alias_definition=$(alias c2)
eval eval alias_parts=( "${alias_definition#alias c2=}" )
$ declare -p alias_parts
declare -a alias_parts='([0]="cut" [1]="-d " [2]="-f2")'
$ printf %q ${alias_parts[1]}
-d\