AWK/至少两个';a';字符,但无';u';人物

AWK/至少两个';a';字符,但无';u';人物,awk,Awk,我写下了下面的AWK脚本,列出了完整路径中至少有两个“a”字母而没有“u”字母的文件 BEGIN {} { if ( (match($1, "^.*[a].*[a]+$") ) ) print $1 } END{} 现在,正如您所能做的,脚本无法消除“u”字母。我必须执行什么修改才能得到我想要的 另外,它通过以下命令从单独创建的名为“data”的文件中读取文件名及其完整路径 find / -name '*' > data “列出完整路径中至少有两个“a”字母且没有“u”字母的文件:

我写下了下面的AWK脚本,列出了完整路径中至少有两个“a”字母而没有“u”字母的文件

BEGIN {}

{
if ( (match($1, "^.*[a].*[a]+$") ) )
print $1
}

END{}
现在,正如您所能做的,脚本无法消除“u”字母。我必须执行什么修改才能得到我想要的

另外,它通过以下命令从单独创建的名为“data”的文件中读取文件名及其完整路径

find / -name '*' > data
“列出完整路径中至少有两个“a”字母且没有“u”字母的文件:”


直接使用此任务的“查找”选项,以避免您的文件
数据

find / -name '*a*a*' -not -name '*u*'
现在,如果您确实需要文件
数据
,那么
sed
就足够了:

sed -n '/a.*a/{/u/!p}' data
如果确实要使用
awk

awk '/a.*a/ { if ($LINE !~ /u/) print ; }' data
对于纯bash版本:

while read -r file; do
    if [[ "$file" = *a*a* ]] && [[ "$file" != *u* ]]; then 
        echo "$file"
    fi
done < data
如果您有很多文件(通常是
/
中的情况),那么最后一个版本将比其他版本慢得多。它将发出所有文件名的声音,然后回显它们。使用
find
的解决方案是最好的,因为文件名在找到时会被回显(和/或处理)


希望这有帮助

因为您使用的是bash,所以不需要像sed、awk或find这样的外部工具就可以做到这一点

#!/bin/bash

shopt -s globstar

for filename in **/*a*a*; do
  [[ "$filename" =~ u ]] || echo "$filename"
done 
如果这绝对是awk,我会使用:

awk '/a.*a/ && ! /u/' data
更新:

根据gniourf_gniourf的礼貌警告,使用路径名扩展(globs)而不是regexp可能会获得更好的性能。这里有一个(非科学的)基准:

$ rm -f file
$ for (( i=1000000; i-- ; )); do echo u >> file; done
$ time bash -c 'while read i; do [[ $i = *u* ]]; done < file'

real    0m8.291s
user    0m6.570s
sys     0m1.717s
$ time bash -c 'while read i; do [[ $i =~ u ]]; done < file'

real    0m10.416s
user    0m8.676s
sys     0m1.735s
$rm-f文件
(i=1000000;i--;);不回u>>文件;完成
$time bash-c'while read i;do[$i=*u*];完成<文件'
实数0m8.291s
用户0m6.570s
系统0m1.717s
$time bash-c'while read i;做[$i=~u]];完成<文件'
实际0m10.416s
用户0m8.676s
系统0m1.735s
“用户”这一行是我们感兴趣的

这使得fileglob的运行速度似乎比regex快30%,测试了一百万条记录,并取得了积极的结果

奇怪的是,当测试失败时,没有多少改进:

$ time bash -c 'while read i; do [[ $i = *a* ]]; done < file'

real    0m8.244s
user    0m6.601s
sys     0m1.639s
$ time bash -c 'while read i; do [[ $i =~ a ]]; done < file'

real    0m9.757s
user    0m8.121s
sys     0m1.630s
$time bash-c'在读取i时;do[$i=*a*];完成<文件'
real 0m8.244s
用户0m6.601s
系统0m1.639s
$time bash-c'while read i;做[$i=~a]];完成<文件'
实际0m9.757s
用户0m8.121s
sys 0m1.630s

在这数百万次测试中,速度仅提高了23%。如果这种shell脚本的优化是很重要的(因为你运行了数百万的测试,并且不觉得你有多余的CPU周期),那么请在你的进程从AWK到BASH时考虑GnuurfgGiuurf的建议。< /P>我必须使用AWK,正如我所描述的。作业要求这样做。很高兴看到一体化解决方案。@CanSürmeli:请查看ghoti的最新答案。鉴于您的文件名列表,这应该是可接受的答案。这就是说,最好还是避免在一些文件名中首先找到错误。@gniourf_gniourf:我问这个问题只是因为我自己不能弄清楚。我必须使用我描述的AWK。作业要求这样做。你的问题并没有说明这一点。@Canürmeli-为你添加了一个awk解决方案。我想你找不到更紧凑的了。(是的,您可以删除其中的空白。)+1用于awk解决方案,我确信这是OPs老师正在寻找的。不要在bash语句中使用正则表达式,它是无用的、缓慢的和迟钝的。在这种情况下,一个glob就足够了:
[[“$filename”=*u*]]
$ rm -f file
$ for (( i=1000000; i-- ; )); do echo u >> file; done
$ time bash -c 'while read i; do [[ $i = *u* ]]; done < file'

real    0m8.291s
user    0m6.570s
sys     0m1.717s
$ time bash -c 'while read i; do [[ $i =~ u ]]; done < file'

real    0m10.416s
user    0m8.676s
sys     0m1.735s
$ time bash -c 'while read i; do [[ $i = *a* ]]; done < file'

real    0m8.244s
user    0m6.601s
sys     0m1.639s
$ time bash -c 'while read i; do [[ $i =~ a ]]; done < file'

real    0m9.757s
user    0m8.121s
sys     0m1.630s