假设我有一个文件,其中包含许多其他内容,
\命令{arg1,arg2,arg3}
(参数为路径,用/
, .
, 字符和数字表示)
但用户也可以用
\command{arg1,
arg2 ,
arg3
}
也就是说,多行且有多余的空格。
我想找到一个包含在 shell 脚本中的常规模式,以便 n 个变量将包含 n 个参数。如何进行 ?
我设法写了
echo "\command{arg1,
arg2 ,
arg3
}" | sed -n -e 's/\\command//p' | sed 's/,/\n/' | sed 's/{\|}//'
但这仅输出arg1
,我什至不确定如何将其存储在变量中。
有关的:
但我无法将所有这些成分结合起来以获得我想要的东西。
答案1
我想找到一个包含在 shell 脚本中的常规模式,以便 n 个变量将包含 n 个参数
以下创建一个arglist
包含每个参数的 shell 数组:
$ readarray -t arglist < <(echo "\command{arg1,
arg2 ,
arg3
}" | sed -n '/\\command/{ :a;/}/!{N;b a}; s/\\command{//; s/[ \n}]//g; s/,/\n/g; p}')
通过使用该declare
语句,我们可以看到它有效:
$ declare -p arglist
declare -a arglist='([0]="arg1" [1]="arg2" [2]="arg3")'
这是另一个示例,参数位于一行:
$ readarray -t arglist < <(echo "\command{arg1, arg2, arg3, arg4}" | sed -n '/\\command/{ :a;/}/!{N;b a}; s/\\command{//; s/[ \n}]//g; s/,/\n/g; p}')
再说一遍,它有效:
$ declare -p arglist
declare -a arglist='([0]="arg1" [1]="arg2" [2]="arg3" [3]="arg4")'
请注意, 中的空格< <(
至关重要。我们正在重定向来自进程替换的输入。没有空间,bash
将尝试完全不同的东西。
怎么运行的
这个sed
命令有点微妙。让我们一次看一下:
-n
除非明确要求,否则不要打印行。
/\\command/{...}
如果我们找到包含 的行
\command
,则执行大括号中的命令,如下所示::a;/}/!{N;b a}
这会将行读入模式缓冲区,直到我们找到包含 的行
}
。这样,我们就可以立即输入整个命令。s/\\command{//
取下
\command{
绳子。s/[ \n}]//g
删除所有空格、右大括号和换行符。
s/,/\n/g
用换行符替换逗号。完成此操作后,每个参数都位于单独的行上,这正是我们
readarray
想要的。p
打印。
答案2
和perl
:
perl -l -0777 -ne '
$n = 0;
for (/\\command\{\s*(.*?)\s*\}/sg) {
$n++;
$i = 0;
for $arg (split /\s*,\s*/, $_) {
$arg =~ s/'\''/$&\\$&$&/g;
print "arg${n}[$i]='\''$arg'\''";
$i++;
}
}
print "n=$n"' the-file
会输出类似:
arg1[0]='arg1'
arg1[1]='arg2'
arg1[2]='arg3'
n=1
你可以这样评估:
eval "$(perl ...)"
为每个s创建$arg1
, ... 数组。$arg2
\command