如何循环linux shell中模式的字符串?
我有一个脚本,可以在目录中的文件中查找字符串,如如何循环linux shell中模式的字符串?,linux,string,bash,awk,split,Linux,String,Bash,Awk,Split,我有一个脚本,可以在目录中的文件中查找字符串,如:tagName:,它可以很好地用于单个:tag:,但不能用于多个:tagOne:tag2:tag3:标记 我当前的脚本包括: 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 com
:tagName:
,它可以很好地用于单个:tag:
,但不能用于多个:tagOne:tag2:tag3:
标记
我当前的脚本包括:
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:
而的目标是将其放入单个:标记的列表中:
同样,问题是,如果一行有多个标记,那么该行根本不会出现在输出中(而问题仅仅是只显示该行的第一个标记)。显然,| sed|代码>存在问题
**我想将:tagOne:tagTwo:etcTag:
转换为:
:tagOne:
:tagTwo:
:etcTag:
政治:暴力:
等等
冒号不是必需的,tagOne
与:tagOne:
一样好(也许更好,但这并不重要)
问题是,如果一行有多个标记,那么该行根本不会出现在输出中(与此相反,问题仅仅是只显示该行的第一个标记)。显然,| sed|代码>存在问题
因此,我应该用更好的东西来替换sed
我试过了:
更聪明的sed:
grep -rh -e '^:\S*:$' ~/Documents/wiki/*.mkd ~/Documents/wiki/diary/*.mkd | \
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|\1\r:\2|g' | \
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|\1\r:\2|g' | \
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|\1\r:\2|g' | \
sort -u
…除了产生奇怪的结果外(对于数量有限的标记),它还能工作,例如:
:toxicity:p:
:somewhat:y:
:people:n:
…将奇怪的随机字母放置在某些标记的末尾,其中:p:
是:leadership:
标记的最后一个字符,并且“leadership”不再出现在列表中。与:y:
和:n:
相同
我也尝试过用几种方法使用循环
grep -rh -e '^:\S*:$' ~/Documents/wiki/*.mkd ~/Documents/wiki/diary/*.mkd | \
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|\1\r:\2|g' | \
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|\1\r:\2|g' | \
sed -r 's|(:[Aa-Zz]*:)([Aa-Zz]*:)|\1\r:\2|g' | \
sort -u | grep lead
…这与的问题相同:领导力:
标签丢失等。
就像
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 "$t\n";
done
done | sort -u
…它根本不分离标签,只打印如下内容:
:特鲁阿玛:领导力:商业:毒性
我应该采取其他方法吗?在循环内使用不同的实用程序(可能是cut
)?也许用python来做这件事(我有一些python脚本,但不太懂这门语言,但这样做可能很容易)?每次我看到awk
我都会想“EEK!”,所以我更喜欢非awk解决方案,更喜欢坚持我使用过的范例,以便更好地学习它们。在grep
中使用PCRE(如果可用)和积极回顾:
OPs初始grep生成的样本数据
:
$ cat tags.raw
:politics:violence:
:positivity:
:positivity:somewhat:
:psychology:
:socialServices:family:
:strategy:
:tech:
:therapy:babylon:
:trauma:
:triggered:
:truama:leadership:business:toxicity:
:unfurling:
:tagOne:tagTwo:etcTag:
$ cat tags.raw
:politics:violence:
:positivity:
:positivity:somewhat:
:psychology:
:socialServices:family:
:strategy:
:tech:
:therapy:babylon:
:trauma:
:triggered:
:truama:leadership:business:toxicity:
:unfurling:
:tagOne:tagTwo:etcTag:
一个while/for/printf
idea基于关联数组:
unset arr
typeset -A arr # declare array named 'arr' as associative
while read -r line # for each line from tags.raw ...
do
for word in ${line//:/ } # replace ":" with space and process each 'word' separately
do
arr[${word}]=1 # create/overwrite arr[$word] with value 1;
# objective is to make sure we have a single entry in arr[] for $word;
# this eliminates duplicates
done
done < tags.raw
printf ":%s:\n" "${!arr[@]}" | sort # pass array indices (ie, our unique list of words) to printf;
# per OPs desired output we'll bracket each word with a pair of ':';
# then sort
上述两种情况都会产生:
:babylon:
:business:
:etcTag:
:family:
:leadership:
:politics:
:positivity:
:psychology:
:socialServices:
:somewhat:
:strategy:
:tagOne:
:tagTwo:
:tech:
:therapy:
:toxicity:
:trauma:
:triggered:
:truama:
:unfurling:
:violence:
:babylon:
:business:
:etcTag:
:family:
:leadership:
:politics:
:positivity:
:psychology:
:socialServices:
:somewhat:
:strategy:
:tagOne:
:tagTwo:
:tech:
:therapy:
:toxicity:
:trauma:
:triggered:
:truama:
:unfurling:
:violence:
使用awk的另一个想法
OPs初始grep生成的样本数据
:
$ cat tags.raw
:politics:violence:
:positivity:
:positivity:somewhat:
:psychology:
:socialServices:family:
:strategy:
:tech:
:therapy:babylon:
:trauma:
:triggered:
:truama:leadership:business:toxicity:
:unfurling:
:tagOne:tagTwo:etcTag:
$ cat tags.raw
:politics:violence:
:positivity:
:positivity:somewhat:
:psychology:
:socialServices:family:
:strategy:
:tech:
:therapy:babylon:
:trauma:
:triggered:
:truama:leadership:business:toxicity:
:unfurling:
:tagOne:tagTwo:etcTag:
一个awk
idea:
awk '
{ split($0,tmp,":") # split input on colon;
# NOTE: fields #1 and #NF are the empty string - see END block
for ( x in tmp ) # loop through tmp[] indices
{ arr[tmp[x]] } # store tmp[] values as arr[] indices; this eliminates duplicates
}
END { delete arr[""] # remove the empty string from arr[]
for ( i in arr ) # loop through arr[] indices
{ printf ":%s:\n", i } # print each tag on separate line leading/trailing colons
}
' tags.raw | sort # sort final output
注意:我对awk对数组进行内部排序(从而消除外部排序
调用)的能力不太了解,因此我对建议持开放态度(或者有人可以将此答案复制到新答案并使用所述能力进行更新?)
上述因素还产生:
:babylon:
:business:
:etcTag:
:family:
:leadership:
:politics:
:positivity:
:psychology:
:socialServices:
:somewhat:
:strategy:
:tagOne:
:tagTwo:
:tech:
:therapy:
:toxicity:
:trauma:
:triggered:
:truama:
:unfurling:
:violence:
:babylon:
:business:
:etcTag:
:family:
:leadership:
:politics:
:positivity:
:psychology:
:socialServices:
:somewhat:
:strategy:
:tagOne:
:tagTwo:
:tech:
:therapy:
:toxicity:
:trauma:
:triggered:
:truama:
:unfurling:
:violence:
通过tr
的管道可以将这些字符串拆分为单独的行:
grep -hx -- ':[:[:alnum:]]*:' ~/Documents/wiki{,/diary}/*.mkd | tr -s ':' '\n'
这也将删除冒号,并且输出中将出现一个空行(易于修复,请注意,由于前导的:
,空行始终是第一行)。添加sort-u
对重复项进行排序和删除,或添加awk'!查看[$0]+'
以删除重复项而不进行排序
使用sed
的方法:
sed '/^:/!d;s///;/:$/!d;s///;y/:/\n/' ~/Documents/wiki{,/diary}/*.mkd
这也会删除冒号,但避免添加空行(在使用y
将剩余的:
音译为
之前,先用s
删除前导/尾随的:
)。sed可与tr结合使用:
sed '/:$/!d;/^:/!d;s///' ~/Documents/wiki{,/diary}/*.mkd | tr -s ':' '\n'
使用awk
处理:
分隔字段,删除重复项:
awk -F: '/^:/ && /:$/ {for (i=2; i<NF; ++i) if (!seen[$i]++) print $i}' \
~/Documents/wiki{,/diary}/*.mkd
awk-F:'/^://&&&&&&:$/{for(i=2;i您提供了一些示例输出(您想要什么;您的脚本生成什么),但您没有提供任何示例输入;请使用与您的输出相对应的示例输入更新问题sok,提供了一些示例输入谢谢:)越来越近,但是…有12行示例输入,但是您的输出(当前,预期)与这12行不匹配,例如,tagOne
,tagTwo
,etcTag
和人
显示在您的输出中,但不显示在输入中;如果问题被更新,则输出(当前,预期)会有所帮助与这12行示例输入相对应;如中所述,您需要向我们提供重现问题以及解决方案所需的详细信息。现在,请认为一切都有意义:)eeek!所有awk答案都是什么?!!!您能解释为什么需要使用perl风格的正则表达式而不仅仅是-e
?人吗grep
:-P--将模式解释为与Perl兼容的正则表达式(PCREs)-e
的目的实际上只是为了消除正则表达式以破折号开头时的歧义。eek:)向上投票,谢谢!数组是必要的吗?我喜欢看循环示例,谢谢。是否可以简单地在for循环中自己的行上打印单词
(排序-u
可以确保它们是唯一的)是的,这是可行的;我添加阵列(自动删除DUP)的唯一原因是我不知道您计划对下游数据做什么,即,虽然Q&A要求只显示唯一列表,但它没有说明您计划对列表做什么(例如,您是否需要使用此列表进行后续处理)因此,数组为您提供了一组数据,您可以在以后“重复使用”,而无需重新处理原始数据;给我一分钟时间,我将添加另一个部分来消除数组,以支持打印/排序
。@alec是的,目的是用您的命令替换标记。原始
,但您需要正确的格式;