我有两个文件,我想将file1分成多个部分,这些部分等于file2中的行数。
此处file2中的每一行都将与file1进行比较,而file1中的所有匹配记录都将形成为新文件。
文件1
<AUDIT_RECORD TIMESTAMP="2013-08-26T19:31:17" NAME="Query" CONNECTION_ID="21974096" STATUS="0" SQLTEXT="SHOW COLLATION"/>
<AUDIT_RECORD TIMESTAMP="2013-08-26T19:31:17" NAME="Query" CONNECTION_ID="21974099" STATUS="0" SQLTEXT="SHOW TABLES"/>
<AUDIT_RECORD TIMESTAMP="2013-08-26T19:31:17" NAME="Query" CONNECTION_ID="21974095" STATUS="0" SQLTEXT="SHOW COLLATION"/>
<AUDIT_RECORD TIMESTAMP="2013-08-26T19:31:17" NAME="Query" CONNECTION_ID="21974094" STATUS="0" SQLTEXT="SHOW COLLATION"/>
<AUDIT_RECORD TIMESTAMP="2013-08-26T19:31:17" NAME="Query" CONNECTION_ID="21974099" STATUS="0" SQLTEXT="SHOW COLLATION"/>
<AUDIT_RECORD TIMESTAMP="2013-08-26T19:31:17" NAME="Query" CONNECTION_ID="21974094" STATUS="0" SQLTEXT="SET NAMES utf8"/>
file2的
21974096
21974100
21974095
21974094
21974099
必需的输出:
21974094.txt
==========================================
TIMESTAMP="2013-08-26T19:31:17"
SQLTEXT="SET NAMES utf8"
==========================================
TIMESTAMP="2013-08-26T19:31:17"
SQLTEXT="SHOW COLLATION"
21974099.txt
==========================================
TIMESTAMP="2013-08-26T19:31:17"
SQLTEXT="SHOW COLLATION"
==========================================
TIMESTAMP="2013-08-26T19:31:17"
SQLTEXT="SHOW TABLES"
21974095.txt
==========================================
TIMESTAMP="2013-08-26T19:31:17"
SQLTEXT="SHOW COLLATION"
...
为了用awk实现这一点,我已经编写了如下代码,但它不能满足我的要求。
awk 'NR==FNR{a[$4];next}!($4 in a){ print $2 "\n" $6 "\n=========\n" > $4 ".txt"}' file2 file1
任何人都可以帮助我用awk或任何其他shell命令来实现上述要求。 (它必须生成至少10000个文件,它应该在最多10分钟内完成生成文件。)
如果我执行了以下命令,则几乎达到但不完全满足要求。
awk 'NR==FNR{a[$1];next}{split($4,b,"\"")}(b[2] in a){print $2"\n"$10"\n=========\n" > b[2]".txt"}' file2 file1
从其中一个文件输出
TIMESTAMP="2013-08-26T19:57:34"
SQLTEXT="/*
=========
TIMESTAMP="2013-08-26T19:57:34"
SQLTEXT="/*
=========
TIMESTAMP="2013-08-26T19:57:34"
SQLTEXT="SHOW
但我想要OUTPUT如下
TIMESTAMP="2013-08-26T19:57:34"
SQLTEXT="/*show variables"
=========
TIMESTAMP="2013-08-26T19:57:34"
SQLTEXT="/* select * from table "
=========
TIMESTAMP="2013-08-26T19:57:34"
SQLTEXT="SHOW collations "
意味着我需要为file1指定分隔符为“”并且没有为file2分隔符。
对此有任何帮助吗?
答案 0 :(得分:3)
您应该使用split函数将第四个单词与"
字符分开,以便获得与file2中的值匹配的数字。您还应该在firth区域中a[$1]
。
此脚本应该有效:
awk 'NR==FNR{a[$1];next}{split($4,b,"\"")}(b[2] in a){print $2"\n"$6"\n=========\n" > b[2]".txt"}' file2 file1
更新:
只要file1中没有多余的引号,我们就可以使用"
字符作为字段分隔符:
awk -F\" 'NR==FNR{a[$1];next}($6 in a){print "TIMESTAMP=\""$2"\"\nSQLTEXT=\""$10"\"\n=========\n" > $6".txt"}' file2 file1
我们将输入文件与"
字符分隔为分隔符,因此字段$ 2是时间戳,字段$ 6是conn。 id,并提交10美元是SQLTEXT。
第一个块NR==FNR{a[$1];next}
使用来自file2的连接ID填充数组(对于第一个文件,NR == FNR)。使用($6 in a)
我们过滤第二个文件的行(因为我们在第一个块中调用了next),其连接id是表a
的索引。如果我们找到匹配项,则执行块{print "TIMESTAMP=\""$2"\"\nSQLTEXT=\""$10"\"\n=========\n" > $6".txt"}'
,将相关信息打印到文件conn_id.txt
答案 1 :(得分:2)
这不会使用awk
,但它有效:
while read -r n
do
echo "Generating $n.txt"
grep $n file1 | sed 's/^.*\(TIMESTAMP="[^"]\+"\).*\(SQLTEXT="[^"]\+"\).*$/=======================\n\1\n\2\n/' > $n.txt
# If you don't want an empty file when there's no match, add this line
if [ ! -s $n.txt ]; then rm -f $n.txt ; fi
done < file2
答案 2 :(得分:2)
这是我的解决方案:
#!/usr/bin/gawk -f
BEGIN {
f = ARGV[2]
while (getline id < f) {
ids[id] = 0
}
ARGV[2] = ""
}
match($0, /.*<AUDIT_RECORD.* (TIMESTAMP="[^"]*").* CONNECTION_ID="([^"]*)".* (SQLTEXT="[^"]*").*/, a) {
id = a[2]
if (id in ids) {
key = id "|" ids[id]++
timestamps[key] = a[1]
sqltexts[key] = a[3]
}
}
END {
for (id in ids) {
count = ids[id]
if (count) {
file = id ".txt"
for (i = 0; i < count; ++i) {
key = id "|" i
printf "%s\n%s\n%s\n\n", "==========================================", timestamps[key], sqltexts[key] > file
}
close(file)
}
}
}
使用
运行它 gawk -f script.awk file1 file2
我实际上更喜欢在输入第一个文件的循环之前预处理第二个文件,因为我不喜欢添加不必要的条件检查。
如果它不是您想要的确切输出,您也可以修改printf
。
实际上,在其他解决方案中,gawk的匹配可以允许一个具体确定哪些参数应该被定位,所以如果其他行的格式与其他额外的键/值对略有不同,上面的代码也可以工作。
<强>更新强>
这个更简单但有可能一次打开太多输出文件,具体取决于条目数。
#!/usr/bin/gawk -f
BEGIN {
f = ARGV[2]
while (getline id < f) {
ids[id] = 0
}
ARGV[2] = ""
}
match($0, /.*<AUDIT_RECORD.* (TIMESTAMP="[^"]*").* CONNECTION_ID="([^"]*)".* (SQLTEXT="[^"]*").*/, a) {
id = a[2]
if (id in ids) {
printf "%s\n%s\n%s\n\n", "==========================================", a[1], a[3] > id ".txt"
}
}