如何遍历字符串以获取来自linuxshell的模式?
我有一个脚本可以查看目录中的文件以查找字符串,例如:tagName: 它适用于单个标签:tag:但不适用于多个:tagOne:tagTwo:tagThree:标签。
我当前的脚本执行以下操作:
grep -rh -e '^:S*:$' ~/Documents/wiki/*.mkd ~/Documents/wiki/diary/*.mkd |
sed -r 's|.*(:[Aa-Zz]*:)|1|g' |
sort -u
printf 'nNote: this fails to display combined :tagOne:tagTwo:etcTag:n'
第一行生成这样的输出:
:politics:violence:
:positivity:
:positivity:somewhat:
:psychology:
:socialServices:family:
:strategy:
:tech:
:therapy:babylon:
:trauma:
:triggered:
:truama:leadership:business:toxicity:
:unfurling:
:tagOne:tagTwo:etcTag:
而目标是要获取到的单一列表:tag:的。
同样,问题是如果一行有多个标签,则该行根本不会出现在输出中(与仅显示该行的第一个标签的问题相反)。显然| sed... |那里是有问题的。
**我想把:tagOne:tagTwo:etcTag:它变成:
:tagOne:
:tagTwo:
:etcTag:
等等等等:politics:violence:。
冒号不是必需的,tagOne它与:tagOne:.
该问题是,如果一个行有多个标签,该行根本不会出现在输出(而不是仅仅是只有行的第一个标签被显示的问题)。显然| sed... |那里是有问题的。
所以我应该用sed更好的东西代替...
我试过:
更聪明的 sed:
grep -rh -e '^:S*:$' ~/Documents/wiki/*.mkd ~/Documents/wiki/diary/*.mkd |
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|1r:2|g' |
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|1r:2|g' |
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|1r:2|g' |
sort -u
...它有效(对于有限数量的标签),但它会产生奇怪的结果,例如:
:toxicity:p:
:somewhat:y:
:people:n:
...在某些标签的末尾放置奇怪的随机字母,其中标签:p:的最后一个字符:leadership:和“领导”不再出现在列表中。:y:和相同:n:。
我也尝试过以几种方式使用循环......
grep -rh -e '^:S*:$' ~/Documents/wiki/*.mkd ~/Documents/wiki/diary/*.mkd |
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|1r:2|g' |
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|1r:2|g' |
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|1r:2|g' |
sort -u | grep lead
...具有相同的:leadership:标签丢失等问题。就像...
for m in $(grep -rh -e '^:S*:$' ~/Documents/wiki/*.mkd ~/Documents/wiki/diary/*.mkd); do
for t in $(echo $m | grep -e ':[Aa-Zz]*:'); do
printf "$tn";
done
done | sort -u
...根本不分开标签,只是打印如下内容:
:truama:leadership:business:toxicity
我应该采取其他方法吗?使用不同的实用程序(可能cut在循环内)?也许在 python 中这样做(我有一些 python 脚本,但不太了解这门语言,但也许这样做很容易)?每次看到awk我都想“EEK!” 所以我更喜欢非 awk 解决方案,更喜欢坚持我使用过的范例以便更好地学习它们。
回答
使用 PCRE in grep(如果可用)和积极的lookbehind:
$ echo :tagOne:tagTwo:tagThree: | grep -Po "(?<=:)[^:]+:"
tagOne:
tagTwo:
tagThree:
你将失去领先:但仍然获得标签。
编辑:有人提到 awk 吗?:
$ awk '{
while(match($0,/:[^:]+:/)) {
a[substr($0,RSTART,RLENGTH)]
$0=substr($0,RSTART+1)
}
}
END {
for(i in a)
print i
}' file