如何在awk中对文件进行排序

时间:2012-08-04 06:49:59

标签: shell sorting awk

我有一个小问题。我需要根据文件的某个起始字符串对文件进行排序。例如,根据数字04,05或06的这种形式:

04..............
................
................
05..............
................
................
06..............
................
................ etc.. 

这是我的awk代码:http://pastebin.com/dLsWkV3q

或只是在这里:

echo "starting...input file"
read file
echo "reading file..."                                                  

echo "... now sorting..."
cat $file | awk '{
if($1=="04"){
print >> "04_file.txt";
}
if($1=="05"){
print >> "05_file.txt";
 }

if($1=="06"){
print >> "06_file.txt";
 }
}'

echo "finished, bye?"
read wait
echo "bye"

目标是我需要多个文件作为结果,只包含相应的块,对于上面的例子:因此我将有3个文件。 04_file.txt05_file.txt06_file.txt。 AND 05_file.txt没有来自04块的任何行。最终的04_file.txt文件只有这个:

04..............
................
................

我的问题是它还将其他块保存到04_file.txt ..

我将不胜感激任何帮助。非常感谢

1 个答案:

答案 0 :(得分:3)

我假设从04,05等开始的唯一行是分隔不同块的行:

awk '
    BEGIN { mode="unknown" }
    /^04/ { mode="04" }
    /^05/ { mode="05" }
    /^06/ { mode="06" }
          { if (mode != "unknown") print $0 >> sprintf("%s_file.txt", mode)}' < $file

awk基本上是一个根据模式执行操作的环境。每个模式操作语句都具有

形式
pattern { action }

以最简单的形式,模式是与当前输入行匹配的正则表达式。 BEGIN是一个特殊情况,在读取输入之前“匹配”,并且还有一个END“模式”,在输入文件被使用后执行。

执行时awk逐行读取输入文件,并执行模式与行匹配的所有操作。在上面的代码中,如果输入行开始(mode)与04,05等,则设置^变量。最后一行(没有模式)匹配所有行,只是将整行写入相应的文件。

我将尝试在一些伪代码中总结这一点:

mode := "unknown"
for each line of input do
    if line starts with 04 then set mode to 04 endif
    if line starts with 05 then set mode to 05 endif
    if line starts with 06 then set mode to 06 endif

    # mode is now either "unknown" if no 04/05/06 pattern has been read
    # from the file yet or holds the most recently read block start (04/05/06)

    if mode is not "unknown" then
        append whole line to file named 'mode'_file.txt
    endif
endfor

如果您想进一步查看手册页或浏览网页以查看awk。在那里,您还可以了解有关模式部分的更多信息,它可以做的不仅仅是匹配当前输入行,如上例所示。


如果所有块都以两位数(任何数字)开头,则上面的代码可以缩短为

awk '
    BEGIN { mode="unknown" }
    /^[[:digit:]][[:digit:]]/ { mode=substr($0, 1, 2) }
          { if (mode != "unknown") print $0 >> sprintf("%s_file.txt", mode)}' < $file