AWK /至少两个'a'字符但没有'u'字符

时间:2012-12-16 13:38:35

标签: awk

我写下了以下AWK脚本,列出了在完整路径中至少有两个'a'字母且没有'u'字母的文件。

BEGIN {}

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

END{}

现在,尽可能地,脚本无法消除'你'字母。我必须做什么修改才能得到我想要的东西?

P.S。它通过以下命令单独创建的名为“data”的文件读取文件名及其完整路径。

find / -name '*' > data

3 个答案:

答案 0 :(得分:4)

由于您正在使用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

“用户”行是我们感兴趣的行。

这使得看起来好像fileglob运行速度比正则表达式快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

这百万次测试的速度提升仅为23%。如果shell脚本的这种优化很重要(因为你运行了数百万次测试并且不觉得你有任何CPU周期可供使用),那么当你的课程从awk转到bash时,请考虑gniourf_gniourf的建议。

答案 1 :(得分:3)

“列出在其完整路径中至少有两个'a'字母且没有'u'字母的文件”:

find / -type f -path "*a*a*" ! -path "*u*" > data

答案 2 :(得分:3)

如何直接使用此任务的查找选项,以便完全避免使用您的文件data

find / -name '*a*a*' -not -name '*u*'

现在,如果你真的需要你的文件data,那么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

对于纯粹的bash版本,根本没有data文件且没有任何find命令,使用globs:

#!/bin/bash

shopt -s globstar
shopt -s nullglob

for file in /**/*a*a*; do
    if [[ "$file" != *u* ]]; then
        echo "$file"
    fi
done

如果您有大量文件(/中通常就是这种情况),那么最后一个版本将比其他版本慢得多。它将覆盖所有文件名,然后回显它们。使用find的解决方案是最好的,因为文件名将在找到时被回显(和/或处理)。

希望这有帮助!