【问题标题】:How to use tab separators with grep in ash or dash script?如何在 ash 或 dash 脚本中使用带有 grep 的制表符分隔符?
【发布时间】:2014-11-18 19:50:23
【问题描述】:

手头的任务:

我有一个包含四个制表符分隔值的文件:

peter 123   five   apples
jane  1234  four   rubberducks
jimmy 01234 seven  nicknames

我需要根据第二列从这个文件中取出一行,并且值在一个变量中。假设我将数字 123 存储在变量 foo 中。在 bash 中我可以做到

grep $'\s'$foo$'\s'

我离开了彼得的信息,没有别的了。有没有办法在 dash 或 ash 上实现相同的效果?

【问题讨论】:

  • grep "[[:space:]]${foo}[[:space:]]" 使用等效的正则表达式调用 grep,而不使用任何 bash-only 功能。顺便说一句,\s 旨在通过反斜杠字面意思传递给您的 grep 命令,而不是由 shell 解释,并且仅适用于您拥有符合 PCRE 的 grep 的情况(大多数不是);使用[[:space:]] 是更好的做法,无论您的外壳如何。
  • ...也就是说,它“等效于”一种非常糟糕的做法,因为您替换的内容将被解释为正则表达式,而不是原始字符串。对于无害的数字;对于任意内容,不是那么多。

标签: bash shell scripting dash-shell ash


【解决方案1】:

你可以在这里使用awk

var='1234'
awk -v var="$var" '$2 == var ""' f
jane  1234  four   rubberducks

PS:我正在做var "" 以确保var 被视为字符串而不是数字。

【讨论】:

  • 谢谢。我在 dash CLI 上测试了你的建议,并得到了 peter 和 jane,所以它看起来只占第一个选项卡。还是我做错了什么?我在我的脚本中使用了 \s 而不是 \t,因为我知道这是用于一般空白,这使得它更加灵活。我想找到这个的原因有两个……首先我想尽可能地远离 bashism,其次我使用包含busybox的设备,这意味着灰壳。
  • 对不起,我打错了,现在已修复。再试一次。
  • 嗯,开始工作得更好:-) 即使我用实际变量(var=$var 而不是 var='123')替换 123,它也可以工作。但是,当我设置 var='1234' 或使用值为 1234 的实际变量时,它会同时返回 jane 和 jimmy。破折号是否将前导零视为空格或其他内容?
  • 糟糕...作为澄清,我并没有推断您的建议中存在 BASH 主义。只是事实上我的可能有一些:)
  • 因为是数值比较,123401234一样。如果您想要字符串比较,请参阅上面的更新答案。
【解决方案2】:

如果您的文件足够小以至于在 shell 中进行迭代的低效率无关紧要,那么您实际上根本不需要grep。以下内容在任何符合 POSIX 的 shell 中都有效,包括 ash 或 dash:

var=123
while read -r first second rest; do
  if [ "$second" = "$var" ]; then
    printf '%s\t' "$first" "$second"; printf '%s\n' "$rest"
  fi
done

(在实践中,我可能会在此处使用 awk;仅考虑演示)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多