Linux 使用grep脚本进行循环

Linux 使用grep脚本进行循环,linux,bash,grep,Linux,Bash,Grep,我问这是一个新问题,因为人们似乎不理解我最初的问题 我能找出一个单词是否以大写字母开头,后面是9个带代码的字母: echo "word" | grep -Eo '^[A-Z][[:alpha:]]{8}' 这就是我应该做的第一部分。我的实际脚本应该循环遍历作为第一个也是唯一一个参数的文本文件中的每个单词,然后检查这些单词中是否有以大写字母开头且长度为9个字母的 我试过: cat textfile | grep -Eo '^[A-Z][[:alpha:]]{8}' 及 产出: The loud

我问这是一个新问题,因为人们似乎不理解我最初的问题

我能找出一个单词是否以大写字母开头,后面是9个带代码的字母:

echo "word" | grep -Eo '^[A-Z][[:alpha:]]{8}'
这就是我应该做的第一部分。我的实际脚本应该循环遍历作为第一个也是唯一一个参数的文本文件中的每个单词,然后检查这些单词中是否有以大写字母开头且长度为9个字母的

我试过:

cat textfile | grep -Eo '^[A-Z][[:alpha:]]{8}'

产出:

The loud Brown Cow jumped over the White Moon. November October tesTer Abcdefgh Abcdefgha
所以它正确地输出了文件randomtext.txt中的所有单词

那为什么不呢

cat randomtext.txt | grep -Eo '^[A-Z][[:alpha:]]{8}'
工作?

您应该这样做:

$ cat file.txt
The loud Brown Cow jumped over the White Moon. November October tesTer Abcdefgh Abcdefgha
$ printf '%s\n' $(<file.txt) | grep -Eo '^[A-Z][[:alpha:]]{8}$' 
Abcdefgha
(添加了choroba解释的
\b

您应该这样做:

$ cat file.txt
The loud Brown Cow jumped over the White Moon. November October tesTer Abcdefgh Abcdefgha
$ printf '%s\n' $(<file.txt) | grep -Eo '^[A-Z][[:alpha:]]{8}$' 
Abcdefgha

(添加了
\b
就像choroba解释的那样)

问题在于锚。您的模式从<代码> >代码>开始,它与一行的开头匹配,但是要返回的单词位于一行中间。您可以将其替换为
\b
以匹配单词边界。

问题在于锚定。您的模式从<代码> >代码>开始,它与一行的开头匹配,但是要返回的单词位于一行中间。您可以将其替换为
\b
,以便在单词边界处进行匹配。

如果您使用cat,则整行将立即馈送给grep。你应该在给grep喂食之前把单词分开

你可以试试:

cat randomtext | awk '{ for(i=1; i <= NF; i++) {print $i } }' | grep -Eo '^[A-Z][a-z]{8}'

cat randomtext | awk'{for(i=1;i如果您使用cat,则会立即将整行输入grep。您应该在输入grep之前拆分单词

你可以试试:

cat randomtext | awk '{ for(i=1; i <= NF; i++) {print $i } }' | grep -Eo '^[A-Z][a-z]{8}'

cat randomtext | awk'{for(i=1;i单词都是一个接一个的,但是您的
grep
表达式引用了整行

你应该把文件分成几个字:

sed -e 's/\s*\b\s*/\n/g' < file.txt | grep ...
sed-e's/\s*\b\s*/\n/g'
或者更好,因为你只对字母数字序列感兴趣

sed -e 's/\W\W*/\n/g' < file.txt | grep -E '^[A-Z][[:alpha:]]{8}$'
sed-e's/\W\W*/\n/g'
$(行尾)是必需的,否则“Supercalifragilisticexpialidocious”将匹配

(我在{9}中修改了{8},因为您指定了“后面跟着9个字母”,但后来我看到您还声明了“9个字母长”)

顺便说一句,如果您使用{8}和-o,您可能会认为匹配项在不匹配的地方。“-o”表示“仅打印与我的模式匹配的部分”


因此,如果您将“Supercalifragilistic”输入到“^[A-Z][:alpha:][]{8}”,它将接受它作为匹配项并打印“supercalis”。这不是我认为您所要求的。这些单词都是一个接一个的,但是您的
grep
表达式引用了整行

你应该把文件分成几个字:

sed -e 's/\s*\b\s*/\n/g' < file.txt | grep ...
sed-e's/\s*\b\s*/\n/g'
或者更好,因为你只对字母数字序列感兴趣

sed -e 's/\W\W*/\n/g' < file.txt | grep -E '^[A-Z][[:alpha:]]{8}$'
sed-e's/\W\W*/\n/g'
$(行尾)是必需的,否则“Supercalifragilisticexpialidocious”将匹配

(我在{9}中修改了{8},因为您指定了“后面跟着9个字母”,但后来我看到您还声明了“9个字母长”)

顺便说一句,如果您使用{8}和-o,您可能会认为匹配项在不匹配的地方。“-o”表示“仅打印与我的模式匹配的部分”



因此,如果您将“Supercalifragilistic”输入到“^[A-Z][[:alpha:][]{8}”,它将接受它作为匹配项并打印“Supercali”。这不是我想你问的问题。

是的,这就是为什么我用
printf
在换行符上拆分每个单词。这解决了问题,谢谢。你能解释一下\b的作用吗?我从来没有遇到过它。是的,这就是为什么我用
printf
在换行符上拆分每个单词。这解决了问题,谢谢。你能解释一下\b的作用吗?我从来没有遇到过也许这没什么大不了的,但通过这种方式,您只能使用$(getconf ARG_MAX)文件中的字符。此外,由于缺少$..而接受了11个字符的单词,并为第一个解决方案添加了
$
。@Iserni,您弄错了我的命令行为,ARG_MAX没有限制,如您所说,请查看是否要触发预期的错误,尝试执行
grep-Eo$(/dev/null
你是对的;它依赖于shell。如果你使用内部的
printf
(例如bash),它会工作;如果它通过
/usr/bin/printf
,它会失败。我仍然认为这有点危险,我宁愿使用
sed
,但是嘿,TMTOWTDI:-)可能没什么大不了的,但这样你就只限于$(getconf ARG_MAX)文件中的字符。此外,由于缺少$..而接受了11个字符的单词,并为第一个解决方案添加了
$
。@Iserni,您弄错了我的命令行为,ARG_MAX没有您在这里所说的限制,如果您想触发预期的错误,请尝试执行
grep-Eo$(/dev/null
你是对的;它依赖于shell。如果你使用内部的
printf
(例如bash),它就可以工作;如果它通过
/usr/bin/printf
,它就失败了。我仍然认为这有点危险,我宁愿使用
sed
,但是嘿,TMTOWTDI:-)
cat;grep
是无用的,请参见(
grep
可以直接访问文件)
cat | grep
没有用,请参阅(
grep
可以直接访问文件)
cat | awk
没用,
awk
可以自己做。@sputnick我认为awk可以对stdin做出反应是非常有用的。想必你会希望该命令与示例随机文本以外的其他源一起工作。但是无论如何,谢谢你的奖励!
cat | awk
没用,
awk
可以自己做。@sputnick我想我可以awk可以对stdin做出反应,这是非常有用的。可能您希望该命令与示例文本以外的其他源一起工作。但是无论如何,感谢您的奖励!