【问题标题】:Awk to read file as a wholeawk 整体读取文件
【发布时间】:2017-04-06 09:06:38
【问题描述】:

让一个文件内容如下-

abcdefghijklmn
pqrstuvwxyzabc
defghijklmnopq

一般来说,如果使用 awk 执行任何操作,它会逐行迭代并在每一行上执行该操作。

例如:

awk '{print substr($0,8,10)}' file

O/P:

hijklmn
wxyzabc
klmnopq

我想知道一种方法,其中文件中的所有内容都被视为单个变量,awk 只打印一个输出。

所需的 O/P 示例:

hijklmnpqr

对于给定的问题,我并不希望得到所需的输出,但总的来说,如果有人能提出一种方法将文件的内容作为一个整体提供给 awk,我将不胜感激。

【问题讨论】:

  • 您指的是没有出现的“给定问题”。你能指定你的“期望输出”吗?
  • 如果你自己阅读你的问题,你能理解要求吗?
  • @inian 没有办法绕过它吗?有什么具体的标志可以帮助我做到这一点吗?
  • @kent 很抱歉,但我尽量让自己清楚。如果你能告诉我你到底哪里不明白,我可以帮你详细说明

标签: linux bash shell awk


【解决方案1】:

这是gawk 解决方案

来自docs

有时您可能希望将整个数据文件视为一条记录实现这一点的唯一方法是给 RS 一个您知道不会出现在输入文件中的值。 这很难以一般方式实现,因此程序始终适用于任意输入文件。


$ cat file
abcdefghijklmn
pqrstuvwxyzabc
defghijklmnopq

RS 必须设置为存档中不存在的模式,遵循文档中的Denis Shirokov 建议(感谢@EdMorton):

$ gawk '{print ">>>"$0"<<<<"}' RS='^$' file
>>>abcdefghijklmn
pqrstuvwxyzabc
defghijklmnopq

abcdefghijklmn
pqrstuvwxyzabc
defghijklmnopq
<<<<

技巧粗体

它通过将 RS 设置为 ^$ 来工作,这是一个永远不会出现的正则表达式 如果文件有内容则匹配。 gawk 将文件中的数据读入 tmp,试图匹配 RS。 每次读取后匹配都会失败,但很快就会失败,因此 gawk 会用文件的全部内容填充 tmp


所以:

$ gawk '{gsub(/\n/,"");print substr($0,8,10)}' RS='^$' file

返回:

hijklmnpqr

【讨论】:

  • 感谢@klashxx。那么你能解释一下这个 RS 在做什么吗?
  • 文件是否作为一个整体进入 awk 的输入?
  • 哇!! @klashxx 希望我能对此投一千票。从来没有遇到过这个实用程序(RS)。阅读关于 awk 的 github 文档也很有趣。非常感谢你:)
  • 我想一次引导文件的全部内容,这样通过给出的示例,我可以打印从索引 8 开始的 10 个字符,将整个文件的内容放入图片中(而不是执行 awk在文件的每一行上一个接一个地生成完全不同的输出)。问题中的示例问题只是一个测试用例,用于阐明我到底想要做什么。 bash 编程比较新,我在这里向你们学习。
  • 据我所知,只是因为它正在对每一行执行操作。但我真的希望听到“为什么?”如果你愿意的话,请给你..
【解决方案2】:

使用 GNU awk 进行多字符 RS(最佳方法):

$ awk -v RS='^$' '{print substr($0,8,10)}' file
hijklmn
pq

如果您的输入不能包含 NUL 字符,则使用其他 awk:

$ awk -v RS='\0' '{print substr($0,8,10)}' file
hijklmn
pq

与其他 awk 不同:

$ awk '{rec = rec $0 ORS} END{print substr(rec,8,10)}' file
hijklmn
pq

请注意,这些都不会产生您想要的输出:

hijklmnpqr

因为他们会按照您说的做(换行符只是输入文件中的另一个字符,没什么特别的):

"read file as a whole"

要获得您想要的输出,首先需要从文件中删除所有换行符。您可以使用gsub(/\n/,"") 或其他各种方法来做到这一点,例如:

$ awk '{rec = rec $0} END{print substr(rec,8,10)}' file
hijklmnpqr

如果那是真的你想要的。

【讨论】:

  • 你是对的,我正是想要这个东西。我发布了前十个字符作为示例输出,但我想要的只是读取整个文件。
  • 好的,你明白了,但请注意,像这样将整个输入读入内存很少能解决任何问题。
  • 最后一个简短的问题.. awk 默认有RS='\n'吗?
  • 不,awk 默认使用代表操作系统中换行符的任何内容作为 RS 值。在 UNIX 上是字符 \n,在 Windows 上是字符对\r\n。请注意,这意味着如果您在 WIndows 上创建了一个文件,那么 WIndows 上的 awk 将正确处理它的 \r\n 行结尾,但是如果您随后将该文件发送到 UNIX 并在其上运行 awk ,那么 awk 将无法执行您想要的操作直到您在输入文件上运行 dos2unix 或类似内容以将 \r\n 行结尾转换为 \ns。
  • 谢谢你的一切:)
猜你喜欢
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
  • 1970-01-01
  • 1970-01-01
  • 2015-01-21
相关资源
最近更新 更多