尝试打印没有12列的文件的文件名。
这适用于命令行:
for i in *dim*; do awk -F',' '{if (NR==1 && NF!=12)print FILENAME}' $i; done;
当我尝试在python脚本中将它嵌入subprocess.call时,它不起作用:
subprocess.call("""for %i in (*dim*.csv) do (awk -F, '{if ("NR==1 && NF!=12"^) {print FILENAME}}' %i)""", shell=True)
我收到的第一个错误是“此时打印意外”,所以我用Google搜索并在括号内添加^。下一个错误是“意外的换行符或字符串结束”,因此再次搜索并在NR == 1&& NF!= 12。使用当前代码,它在每个文件中打印了许多行,因此我怀疑if语句有问题。我在subprocess.call中以这种方式使用了awk和循环,但没有结合使用if语句。
答案 0 :(得分:0)
在传递给subprocess.call()
的字符串中,您的if
语句正在评估字符串(可能不是您想要的比较)。通过在AWK中执行所有操作来简化shell命令可能更容易。您正在为shell的$i
循环中的每个for
执行AWK。由于您可以向AWK提供多个输入文件,因此实际上不需要此循环。
您可能希望扫描整个文件,直到找到任何行不超过12个字段,而不仅仅检查第一行(NR==1
)。在这种情况下,条件仅为NF!=12
。
如果您只想检查每个文件的第一行,则在使用多个文件时NR==1
会变为FNR==1
。 NR
是“记录数”(跨所有输入文件),FNR
是当前输入文件的“记录文件数”。这些是AWK中的特殊内置变量。
此外,AWK的语法允许仅在行匹配某些条件时才执行块。没有条件(正如你所做的那样)为每一行运行块。例如,要扫描提供给AWK的所有文件并在第一行上打印除12个字段以外的文件的名称,请尝试:
awk -F, 'FNR==1 && NF!=12{print FILENAME; nextfile}' *dim*.csv
我已将.csv
添加到您的通配符*dim*
中,就像在Python版本中一样。 -F,
当然会将字段分隔符从默认空间更改为逗号。对于每个文件中的每一行,AWK检查字段NF
的数量是否为12,如果不是,则执行代码块,否则它将继续执行下一行。此块打印AWK正在处理的当前文件的FILENAME
,然后使用nextfile
跳到下一个文件的开头。
尝试使用Python中的subprocess
模块运行此AWK版本:
subprocess.call("""awk -F, 'FNR==1 && NF!=12{print FILENAME; nextfile}' *dim*.csv""", shell=True)
三重引号使其成为文字字符串。 AWK的输出转到 stdout ,我假设您知道如何在Python中使用subprocess module。
不要忘记Python本身就是一种富有表现力和强大的语言。如果您已经在使用Python,那么使用 only Python 而不是混合使用Python,bash和AWK可能更简单,更容易,更轻松。
您可以找到文件的名称(从*dim*.csv
中选择),每个文件的第一行包含12个以逗号分隔的字段:
import glob
files_found = []
for filename in glob.glob('*dim*.csv'):
with open(filename, 'r') as f:
firstline = f.readline()
if len(firstline.split(',')) != 12:
files_found.append(filename)
f.close()
print(files_found)
glob
module给出了与通配符模式*dim*.csv
匹配的文件列表。读取每个文件的第一行并将其拆分为以逗号分隔的字段。如果这些字段的数量不是12,则会将其添加到列表files_found
。