在我的一门计算机科学课上,我的老师给了我们一个用户文件:users.txt
.该文件的行如下所示:
$ head users.txt
root:x:0:0:root:/root:/bin/bash
apache:x:71:71:system user for apache2:/var/www:/bin/sh
ftp:x:73:73:system user for proftpd:/var/ftp:/bin/false
c0407115:x:1501:1000:Alberto Damiao Canelas Fraga:/home/c0407115:/bin/bash
c0407165:x:1502:1000:Alexandre Viriato Morais Magalhaes:/home/c0407165:/bin/bash
c0407110:x:1503:1000:Alvaro Manuel Figueiredo Nunes de Sousa:/home/c0407110:/bin/bash
c0307009:x:1504:1000:Ana Marta Tavares Laranjeira:/home/c0307009:/bin/bash
c0416079:x:1505:1000:Ana Rita Caetano Mourato:/home/c0416079:/bin/bash
c0407137:x:1506:1000:André Brito Coimbra:/home/c0407137:/bin/bash
c0307068:x:1507:1000:André Filipe Rios da Fonseca Alves Modesto:/home/c0307068:/bin/bash
然后老师要求做以下事情:
编写一个命令,列出所有非学生用户(也就是说,他们的登录名不是以 c 开头的??)
我的第一个方法如下:
$ cat users.txt | grep [^c]*
grep: figures: Is a directory
grep: practice: Is a directory
我收到与我正在处理的目录中的某些目录相关的错误消息。这些是我的目录中的当前文件:
$ ls
archive figures practice users.txt
然后我尝试做相反的事情:使用反向匹配选项:
$ cat users.txt | grep -v [c]*
$
但这次我没有任何输出。为什么这不起作用,为什么我收到该错误消息,以及如何做到这一点?谢谢
答案1
... | grep [^c]*
这里,[^c]*
是一个 glob,一个文件名模式,类似于 例如*.txt
。
其[^c]
含义与正则表达式中的含义相同,即它匹配不是 的任何单个字符c
。与正则表达式不同,*
匹配全局中任意数量的任意字符。因此,整个内容匹配并扩展到任何不以 开头的文件名c
,例如所有archive figures practice users.txt
.
当给定参数列表时,不带-e
或-f
选项,grep
将第一个参数作为模式,因此该命令将archive
在其余文件中查找该字符串。grep
默认情况下不处理目录,因此您会收到这些错误。
grep
如果该模式包含 shell 特有的字符,则需要引用该模式以使其保持不变。或者为了安全起见,如果有任何特殊字符,请引用该模式。
作为正则表达式,[^c]*
将匹配任意数量的不是 的连续字符c
。但由于这包括零长度匹配,grep '[^c]*'
因此将匹配任何行。
您需要将模式锁定到行的开头,并使其至少需要一个字符。
由于这是一项作业,请尝试这些命令,看看您是否可以找出它们为什么这样做:
grep c users.txt
grep -v c users.txt
grep ^c users.txt
grep -v ^c users.txt
grep '^[^c]' users.txt
grep -v '^[^c]' users.txt
([c]
与 just 相同c
,所以我将省略那个。它本身^
对于 shell 来说实际上并不特殊,所以不需要在这里引用。那里的一些模式可能与其他一些模式等效。)
答案2
您使用了错误的正则表达式。这是正确的:
cat ./users.txt | grep -v '^c'
您也可以在不使用的情况下执行此操作cat
:
grep -v '^c' ./users.txt