【问题标题】:How to add quotes for awk when single and double quotes are already used?已经使用单引号和双引号时如何为 awk 添加引号?
【发布时间】:2022-01-04 20:33:07
【问题描述】:

我想写一个别名,以便我的 squeue 命令只输出正在运行的模拟。对于我的 squeue 命令,我的 .bashrc 中有一个别名,如下所示

alias sq='squeue -u as1056 --format="%.18i %.36j %.8u %.2t %.10M %.10L %.6D %.6C %.12P %R"'

有了这个,我可以将正在运行的模拟输出为

sq | awk '$4 == "R" {print $0}'

这在命令行中按预期工作。我现在想将此命令添加为别名

alias sqrun='sq | awk "$4 == \"R\" {print $0}"'

如您所见,等号后的单引号已经用尽,因此在 awk 命令后需要双引号。但是,要匹配第 4 列中的模式,我需要指定另一个字符串。由于已经使用了单引号和双引号,我不确定在这种情况下如何指定字符串。我尝试使用反斜杠转义双引号,但它会引发错误:

awk: cmd. line:1:  == "R" {print -bash}
awk: cmd. line:1:  ^ syntax error

那么在这种情况下我应该如何指定别名呢?

Edit1:通过在 sq 命令中匹配一个简单的 R 模式,这是一种肮脏的方式。问题是它经常匹配包含单词“DRAINED”的列。所以我可以使用 sed 删除这些行。所以像

sq | awk "/R/ {print $0}" | sed "/DRAINED/d"

不会遇到命令中有 3 个引号的问题。但是我想避免这种方法,因为它不是通用的,并且如果碰巧有一列包含 R 并且不包含单词“DRAINED”,则可能会给出错误的结果。

PS:这是我关于 stackoverflow 的第一个问题,所以如果您发现我提出这个问题的方式有任何错误,我将非常感谢您的反馈!

【问题讨论】:

  • 使用函数代替别名会更容易
  • 感谢您的提示!在一般用法中,是否最好在 .bashrc 中定义函数而不是别名?还是您只是为了避免引号问题而提及它?

标签: bash awk


【解决方案1】:

我会选择一个简单的:

alias sqrun='sq | awk '\''$4 == "R" {print $0}'\'

或者使用@DiegoTorresMilano 建议的函数(但与别名不同,要找到忘记的函数名称并不容易):

sqrun() { sq | awk '$4 == "R" {print $0}'; }

或者如果有多个别名要定义:

#!/bin/sh

# A little magic that will show you the way:
while IFS='' read -r cmd
do
    # define a dummy alias
    alias "unamed=$cmd"
    # then show it
    alias unamed
done <<'EOF'
squeue -u as1056 --format="%.18i %.36j %.8u %.2t %.10M %.10L %.6D %.6C %.12P %R"
sq | awk '$4 == "R" {print $0}'
EOF

现在您可以将输出复制粘贴到您的 .bashrc 并为您的别名命令设置名称

注意事项:

  • &lt;&lt;'EOF' ... EOF 是一个引用 here-document;它将向命令的标准输入(while 循环)提供其内容。当引用时,意味着shell不会扩展它里面的任何东西。

  • read 命令从标准输入读取一行(由 here-document 提供)。 IFS=''-r 选项用于防止 read 修改行。

【讨论】:

  • 谢谢!我对bash不太熟悉,所以到目前为止我还不知道如何定义函数。你写的完全按照预期工作!您能解释一下您编写的第三段代码吗?它看起来非常有用,因为我有很多别名命令,但是里面的很多东西对我来说都是新的,我不确定我应该搜索什么才能理解它。
  • 我添加了一些解释,我希望它会足够;-)
  • 不要编写循环来处理此处的文档以创建别名。只是,没有。
  • 函数并不难找。 Bash 在他们的名字上完成,你可以随时输入set 来查看列表。如果您将所有函数命名为以小写字母开头,则为set | grep '^[a-z]'。这减少了使用前导下划线或大写字母的发行版配置文件脚本中的内容。
  • @Kaz 我不使用函数来替换别名,但它们可以完成这项工作,是的。通过heredoc和循环定义别名有什么问题?没有转义问题,没有双引号/单引号问题,易于阅读和维护,但需要进行一些处理。
【解决方案2】:

您可以通过双引号单引号链接单引号部分

alias sqrun='sq | awk '"'"' $4 == "R" {print $0} '"'"' '

为清楚起见添加了额外的空格,但不是必需的。然而,这些嵌套的引号可能会变得非常难以阅读,并且可能不是一个好主意,除非只是用于琐碎的情况和丢弃的脚本。

【讨论】:

  • 我不知道为什么,但是当只是在命令行中运行sq | awk '"'"' $4 == "R" {print $0} '"'"' 时,它会输出整个 sq 命令,而不仅仅是正在运行的模拟。
【解决方案3】:

awk 脚本包含 $,当您将 awk 脚本周围的引号从 ' 更改为 " 时,它会使 bash 将它们视为要替换的变量。你还得逃跑$:

alias sqrun='sq | awk "\$4 == \"R\" {print \$0}"'

【讨论】:

  • 感谢您的解释!我应该注意到 bash 也使用 $ 所以可能会有一些冲突。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-10
  • 2016-11-08
  • 2017-12-07
相关资源
最近更新 更多