>我需要替换名称中"无关紧要"的部分。这需要在 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应更改)
设置extglob
选项。此外,删除引号,并将空格移到替代项之外。您可以进一步缩短表达式:
#!/bin/bash
line="STIG VAN DE DEN DER WYNKELE"
shopt -s extglob
line=${line//@(VAN|DE?([NR])) }
echo "$line"
通过在最后一行中双引$line,您可以查看空格是否正确删除。
bash
不会回溯。首先,它在输入中找到VAN
:
STIG VAN DE WYNKELE
^^^^^|
(其中|
表示扫描时的指针)。
将VAN
替换为 后,您有
STIG DE WYNKELE
|
你会注意到在从 bash
开始的字符串中找不到D
;你刚刚插入的空格没有被 extglob
选中。
每个模式中删除前导空格,并删除匹配项,而不是将其替换为空格:
echo "${line//@('VAN '|'DEN '|'DE '|'DER ')}"
当然,这样做的问题是,您现在可能会删除出现在单词末尾的匹配项。没有一场比赛可以避免这种情况;相反,在一个循环中执行多个替换:
for word in VAN DEN DE DER; do
line=${line// $word / }
done
你不需要任何CC_10模式。您可以只使用参数扩展:
${line/ * / }
例:
$ line="STIG VAN DE WYNKELE"
$ echo ${line/ * / }
STIG WYNKELE
<</div>
div class="one_answers"> 使用 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 }'