【问题标题】:WHY NOT use awk inside perl? [closed]为什么不在 perl 中使用 awk? [关闭]
【发布时间】:2014-09-03 09:07:35
【问题描述】:

这个问题可能已经被问过很多次了,关于能否在你的 perl 脚本中包含 awk one liner。但这些问题对以下问题过于具体:

  1. 提供了一种不同的方法作为建议或
  2. 现有代码中的语法已更正或
  3. 大多数时候 -> 解决方案是使用 perl 提供的,因为专家倾向于使用 awk 或 perl,因为它们都做同样的工作。是的。可能。但我认为 awk 是为解决特定问题而设计的,这些问题可以在 awk 中比 perl 更好地解决。

示例:我有ls -lart 的输出,第 9 列是文件名。我可以在 awk 中以 ls -lart|awk '{print $9}' 轻松做到这一点。当然,同样的事情可以使用 perl 使用readdir() 来完成。但是在perl中提取第8列或第7列不是那么容易吗?如果我必须将数据管道提取到 awk 管道到 sed 等,情况会变得更糟。

另一个例子: 我有一个特定的 DIR,其中包含许多格式的文件,例如:

ABC_9090_DEF_10-22-30_13-07-2014.temp

注意 date_time.temp 标记部分。这里的格式是 ABC_4digits_DEF_hours-minutes-seconds_day-month-year

而且我只想查看刚刚创建的新文件(比如从现在开始 5 分钟之前)。使用 awk/sed 的方法是(伪代码,如果您需要我复制实际的一个衬里,请告诉我):

  1. ls -lart|awk '{print $9}'|
  2. egrep提取10-22-30_13-07-2014
  3. 使用 sed 将 _ 替换为 -|awk 以重新排列 以使数字采用 YEARMONTHDAYHOURSMINUTESSECONDS 格式。
  4. 再次使用 awk 使用 if($1>$mynum) 将此数字与变量进行比较(该变量应该有一个相同格式的数字,代表 TODAYS TIME - 5 分钟)

问题: 但由于某种原因(其他复杂性),我想用 perl 编写它,我发现 if 条件 if ($1>$mynum) 在我使用系统命令在 perl 中使用它时会引发错误。即使使用单引号、双引号、无引号,它也会显示使用 '>' 的语法错误。

谁能概括地告诉我:

  1. 如果可以选择,为什么有人在这种情况下不使用 awk,sed 而不是 perl?
  2. 在 perl 中包含 awk 或 sed 时应记住的事项的一般解释并非针对此问题(希望也能解决此特定问题。

【问题讨论】:

  • 请不要解析ls。
  • 这个问题缺乏焦点。无论如何,仅仅因为某事可以被完成并不意味着它是一个好方法。 awk/sed 通常最好直接与 shell 配对,即使 perl 可以 相当容易地调用它们(这并不意味着它是一个好方法)。
  • 您可以使用ls | sort 轻松执行此类任务。有时,不太复杂的解决方案并不明显,或者可能被忽视。
  • 伙计们,也许您正在寻找解决特定问题的方法。但我需要的是一个“通用”的答案。因此,我用一个例子问了一个一般性问题,只要求通用答案。
  • 事情是你的例子很糟糕。您使用了错误的工具 - 如果您想查找在过去五分钟内创建的文件,请使用 find-mtime(或其他时间开关)。您的问题是一个相当简单的语法问题。没有通用的“不要在 perl 中使用 foo”,只是 perl 可以做任何 awk 和 sed 可以做的事情。所以只要使用正确的工具。

标签: regex perl awk sed


【解决方案1】:

如果可以选择,为什么有人在这种情况下不使用 awk,sed 而不是 perl?

如果你喜欢这个想法:

  • 从 perl 派生一个 shell
  • 在外壳内
  • 再次分叉两个进程(ls 和 awk)只会打印第 9 列

请随意。这对我来说听起来是个糟糕的主意,但你知道:你的里程......

在 perl 中包含 awk 或 sed 时应该记住的事情的一般解释不是针对这个问题的(希望也能解决这个特定问题:))

要记住的一般事项:

  • $variables 的转义规则 - 如 $9 可以解释的内容:
    • perl 本身(例如,$9 可以是存储正则表达式捕获的 perl 变量)
    • 通过分叉的外壳(例如,$9 可以是持有第 9 个位置 arg 的 shell 变量)
    • awk(表示第 9 列)
  • 了解如何处理系统错误代码
  • 主要是 - 任何编程任务都需要至少了解所用编程语言的基础知识。 (这就像我的英语 - 很糟糕,但足以写出答案):)

以您为例:ls -lart|awk '{print $9} 是您能做的最糟糕的事情之一。

想象一下:

  • 如果你有文件名:this is my file.txt
  • 什么会打印ls -lart|awk '{print $9}

猜对了,只会打印this。当然,这是错误的。解析文件名什么 来自stdin 总是很糟糕的主意(除非你有以 NULL 结尾的文件名),因为文件名可以包含空格 - 不仅是 spaces,还有 tabnewline 字符。

你的第二个例子:

  • 您可以使用find 来实现所需的目标:print only new files modified in the last 5 min,而不是在链(管道)中运行 4 个程序
  • 使用 perl,您可以使用 perl 模块:
    • File::Find - 可以做任何find 命令所做的事情,甚至更多
    • File::Find::Rule - File::Find 的替代接口
    • 和许多其他模块:see 来自 File::Find 系列
    • 但您可以使用例如Path::TinyClass::Path 或类似模块
    • 等等……

【讨论】:

  • +1 用于解释该方法的问题。一个技巧:从stdin 解析文件名并不总是很糟糕,经典的例子是find ... -print0 | xargs -0l ....。只要文件名以 NULL 结尾,您就可以从标准输入安全地解析它们。
  • @user000001 :) 你完全正确! (print0 | xargs -0 是我在 bash 中的最爱之一)我只是不想给我的答案增加太多复杂性,它只会让 OP 更加困惑......;)
猜你喜欢
  • 2012-04-18
  • 1970-01-01
  • 2012-01-18
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-15
  • 1970-01-01
相关资源
最近更新 更多