我写下了以下AWK脚本,列出了在完整路径中至少有两个'a'字母且没有'u'字母的文件。
BEGIN {}
{
if ( (match($1, "^.*[a].*[a]+$") ) )
print $1
}
END{}
现在,尽可能地,脚本无法消除'你'字母。我必须做什么修改才能得到我想要的东西?
P.S。它通过以下命令单独创建的名为“data”的文件读取文件名及其完整路径。
find / -name '*' > data
答案 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
的解决方案是最好的,因为文件名将在找到时被回显(和/或处理)。
希望这有帮助!