新的 awk 用户在这里。我是一个模拟器的用户,它输出一个单独的ascurry文件,该文件是M行乘N列,空格分隔,每行末尾有换行符。行的数量不重要,但它是在数千。列的数量是数百。我想把这个大文件分成多个小文件,比如说,50列数据。
下面使用 awk 将可靠地使用空格作为分隔符来拆分文件,并打印前3列数据:
awk ‘{split($0,a)} {print a[1] “ “ a[2] " " a[3]}’ huge_file.txt > small_file.txt
有没有什么简单的方法可以让它打印出50列数据,而不需要很长的print语句?理想情况下,我希望它打印出从X到X+49的列。
到目前为止,我不得不使用split函数来获取 awk,以便以我认为可预测的方式分解文件。当我尝试使用类似于:
awk '{print $1 " " $2 " " $3}' huge_file.txt > small_file.txt
它从来没有正确的工作,即使我使用FS = " "
。
如果你能帮忙的话,我将不胜感激。
7条答案
按热度按时间bt1cpqcv1#
也许这个合适
制作一些“测试”数据(220列X 1000行):
将'test.txt'拆分为较小的文件,每个文件包含50列:
更好的格式:
mkshixfv2#
使用GNU awk,你可以使用
FPAT
来定义正则表达式的输入字段(在你的例子中是一组C=50个空格分隔的单词),并只打印第X组:这将打印第三(X=3)组50(C=50)列,即列101到150。当然,如果少于150列,则打印的列数将少于50列(如果少于101列,则打印的列数将少于50列)。
您也可以一次打印不同文件中的所有组:
如果你有N=225列,这将创建5个名为
small.1.txt
,...,small.5.txt
的文件。文件small.1.txt
包含列1到50,small.2.txt
包含列51到100,.,small.5.txt
包含列201到225。演示:
ve7v8dk23#
coreutils
可能更适合此任务(在bash中):qyswt5oh4#
它从来没有正确的工作,即使我使用
FS = " "
。这是GNU
AWK
中FS
的默认值,考虑到给出输出
将内置变量值设置为默认值不会改变结果。
{print $1 " " $2 " " $3}
由于有字段分隔符(
FS
)用于输入,因此通常有字段分隔符(OFS
)用于输出,当您使用逗号分隔print
参数时使用,在这种情况下,它可能会重写为它不仅更简洁,而且您可以通过设置
OFS
值来更改所有分隔符。OFS
的默认值为单空格。如果您想了解更多关于FS
或OFS
的信息,请阅读8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNRclj7thdc5#
下面是我对awk脚本的看法,我认为它可以满足您的需要。与Barmar的答案一样,它使用for循环迭代字段,但这个循环非常简单,awk新手也能理解。:)它将输出重定向到不同的文件,并且不需要GNU awk。
你并不真的需要
output_file
变量,但我觉得它使事情更容易阅读。因为有一个关于它的注解,你应该注意到这并没有显式地关闭文件。关闭文件的版本可能会将以下内容作为
for
循环的最后一行:这会在我们处理完文件后关闭它们,但代价是开销和速度上的一点影响。如果你不需要,我就不麻烦了。
wwtsj6pe6#
这个问题可能会导致awk必须创建更多的输出文件,而不是同时打开,所以这里有一个答案来避免这个问题,而不必在每次写入时打开和关闭输出文件,因为这会很慢。
在每个系统的基础上,一个进程一次可以打开多少个文件是有限制的,在某些系统上,
ulimit -n
会告诉你这个数字。如果你的操作系统支持,GNU awk可以让你通过内部管理按需打开/关闭文件,让你看起来有比一次打开的文件更多的文件,但是一旦进入这个阶段,它就会慢很多。其他awk会出现“打开的文件太多”错误(google awk too many open files)。下面是两种方法来避免这个问题。**1)**每个输出文件打开一次输入文件,并一次一个地写入每个输出文件:
如果您的输入文件可能太大而无法容纳在内存中,那么您可以这样做:
这只是打开和关闭输入和输出文件一次,每个输出文件所需的和使用很少的内存。
**2)**首先将输入文件读入内存,然后一次写入一个完整的输出文件:
或者,如果你的输入确实适合内存,这也可以在任何POSIX awk中工作:
并且会更有效一点,因为它不必重新打开输入文件并重新读取每个输出文件的内容。
我使用上面的
-v FS='^$'
和nf=split($0,tmp," ")
,而不是将FS
设置为" "
,并使用NF
以提高效率。我从nf=split($0,tmp," ")
中使用nf
而不是NF
(并且只在第一个输入行读取时使用),因为有些awk,例如。GNU awk只会在脚本中提到特定字段(如$1
或NF
)时进行字段拆分,否则他们知道您没有使用字段,因此他们不需要浪费时间将输入拆分为字段。以防万一你使用的awk会进行字段分割,我将FS
设置为^$
,这样它只会尝试匹配一个空行,而不是多次分割空格。nwsw7zdq7#
使用
for
循环遍历字段。外部循环以50为一组,并在每组后打印一个换行符。内部循环处理每个组,打印每个字段后面的空白。