我需要更换"微不足道的"名字的一部分。这需要在bash脚本中完成。要做到这一点,我需要删除中间词" VAN"," DEN"," DE"和" DER"。
为此,我使用内置替换(问题减少到2行):
line="STIG VAN DE WYNKELE";
line=${line//@(' VAN '|' DEN '|' DE '|' DER ')/' '};
echo $line;
输出:
STIG DE WYNKELE
预期产出:
STIG WYNKELE
似乎@(...)匹配其中一个中间词,删除了这一个中间词的所有出现,但它并不匹配其他词。
问题:我的语法错误了吗?如果没有,我该如何删除这些词? sed需要文件,而我的输入是变量,更改的文本也应存储在变量中。 ($ line应该改变)
答案 0 :(得分:4)
您需要设置extglob
选项。另外,删除引号,并将空格移到替代项之外。您可以进一步缩短表达式:
#!/bin/bash
line="STIG VAN DE DEN DER WYNKELE"
shopt -s extglob
line=${line//@(VAN|DE?([NR])) }
echo "$line"
通过在最后一行中双引号$,您可以看到空格是否被正确删除。
答案 1 :(得分:3)
bash
没有回溯。首先,它在输入中找到VAN
:
STIG VAN DE WYNKELE
^^^^^|
(其中|
表示扫描时的指针。)
用VAN
替换后,您有
STIG DE WYNKELE
|
您会注意到从DE
开始的字符串中找不到D
; bash
未检查您刚刚插入的空间。
相反,从每个模式中删除前导空格,并删除匹配而不是用空格替换它:
echo "${line//@('VAN '|'DEN '|'DE '|'DER ')}"
当然,问题在于你现在可能会删除在单词结尾处发生的匹配。只用一场比赛就可以避免这种情况;相反,在循环中进行多次替换:
for word in VAN DEN DE DER; do
line=${line// $word / }
done
答案 2 :(得分:0)
您不需要任何extglob
模式。您可以使用参数扩展:
${line/ * / }
示例:强>
$ line="STIG VAN DE WYNKELE"
$ echo ${line/ * / }
STIG WYNKELE
答案 3 :(得分:0)
使用awk:
echo $line | awk '{ if ($2 == "VAN" || $2 == "DEN" || $2 =="DE" || $2=="DER" ) $2=""; if ($3 == "VAN" || $3== "DEN" || $3 =="DE" || $3=="DER" ) $3="" ; print }'