带引号的 Bash awk 命令

ZCT*_*ZCT 8 shell scripting bash

一段时间以来,我一直试图找到这个问题的答案。我正在编写一个快速脚本来运行基于 awk 输出的命令。

ID_minimum=1000
for f in /etc/passwd;
do 
    awk -F: -vID=$ID_minimum '$3>=1000 && $1!="nfsnobody" { print "xfs_quota -x -c 'limit bsoft=5g bhard=6g $1' /home "}' $f;       
done
Run Code Online (Sandbox Code Playgroud)

问题是-c参数采用单引号中的命令,我无法弄清楚如何正确转义它,而且它$1也不会扩展到用户名中。

基本上我只是想让它输出:

xfs_quota -x -c 'limit bsoft=5g bhard=6g userone' /home
xfs_quota -x -c 'limit bsoft=5g bhard=6g usertwo' /home
Run Code Online (Sandbox Code Playgroud)

等等...

Kus*_*nda 13

xfs_quota -x -c 'limit bsoft=5g bhard=6g USER' /home为每个USERUID 至少为的命令运行该命令$ID_minimum,请考虑首先解析这些用户,然后实际运行该命令,而不是尝试创建一个表示您要运行的命令的字符串。

如果您创建命令字符串,则必须这样eval做。这很繁琐而且很容易出错。最好只获取用户名列表,然后运行命令。

getent passwd |
awk -F: -v min="${ID_minimum:-1000}" '$3 >= min && $1 != "nfsnobody" { print $1 }' |
while IFS= read -r user; do
    xfs_quota -x -c "limit bsoft=5g bhard=6g $user" /home
done
Run Code Online (Sandbox Code Playgroud)

请注意,在.之后的参数周围实际上不需要引号-c。在这里我使用双引号是因为我希望 shell 扩展$user包含由awk.

${ID_minimum:-1000}在给命令中的min变量赋值时使用awk。这将扩展到 的值$ID_minimum,或者扩展到该1000变量是否为空或未设置。


如果你真的想,你可以让上面的循环打印出命令而不是执行它们:

getent passwd |
awk -F: -v min="${ID_minimum:-1000}" '$3 >= min && $1 != "nfsnobody" { print $1 }' |
while IFS= read -r user; do
    printf 'xfs_quota -x -c "limit bsoft=5g bhard=6g %s" /home\n' "$user"
done
Run Code Online (Sandbox Code Playgroud)

再次注意,如果您要使用eval或通过其他方式执行生成的命令,则在输出的命令字符串中使用双引号(而不是单引号)不会以任何方式混淆 shell 。如果它困扰你,只需在printf上面的第一个参数中交换单引号和双引号。

  • @TheDudeAbides 假设用户选择 UID 1000 是因为它是系统服务帐户和他们系统上的用户帐户之间的分界线,我们可以推断该用户没有在 macOS 上运行(第一个用户帐户是 501)。此外,在 macOS 上使用 XFS 实用程序_非常不常见_,因为 Apple 并不真正支持 XFS。此外,`/home` 在 macOS 上并没有真正使用(它在那里,但通常是空的)。 (2认同)

ilk*_*chu 6

for f in /etc/passwd;
Run Code Online (Sandbox Code Playgroud)

这有点愚蠢,因为实际上没有只有一个值的循环。

但问题似乎是从 awk 打印单引号。您可以在 shell 中对它们进行转义,但也可以在 awk 中使用反斜杠转义来打印它们。是数值为OOO的字符(八进制),所以是。所以这将是一种方法:\OOO\047'

awk -F: -vID=$ID_minimum '$3>=1000 && $1!="nfsnobody" {
    printf "xfs_quota -x -c \047limit bsoft=5g bhard=6g %s\047 /home\n", $1}' /etc/passwd
Run Code Online (Sandbox Code Playgroud)

您可以在 hex, 中使用类似的转义\x27符,但如果以下字符是有效的十六进制数字,则在某些实现中可能会被误解。(当然,我假设 ASCII 或兼容 ASCII 的字符集,例如 UTF-8。)


mos*_*svy 6

使用-f -awk 选项从 stdin 和 here-document 中获取脚本:

awk -F: -v "ID=$ID_minimum" -f - <<'EOT' /etc/passwd
$3>=1000 && $1!="nfsnobody" {
    print "xfs_quota -x -c 'limit bsoft=5g bhard=6g "$1"' /home "
}
EOT
Run Code Online (Sandbox Code Playgroud)


ZCT*_*ZCT 2

这做到了。

awk -F: -vID=$ID_minimum '$3>=1000 && $1!="nfsnobody" { print "xfs_quota -x -c '"'"'limit bsoft=5g bhard=6g ''"$1"'''"'"' /home "}' /etc/passwd
Run Code Online (Sandbox Code Playgroud)