【问题标题】:Column without last characters with awk and printf使用 awk 和 printf 没有最后一个字符的列
【发布时间】:2022-01-01 21:46:21
【问题描述】:

我有这个脚本:

#!/bin/bash

f_status () {
        systemctl list-units | grep $1 | awk '{ printf("SERVICE STATUS:  %-25s \t %s \t %s \t %s\n",$1,$2,$3,$4) }'
}

f_line() {
        echo "-------------------------------------------------------------------------------------------"
}

echo ""
f_line
f_status "cron"
f_status "ssh"
f_line

这个脚本给了我这样的结果:

-------------------------------------------------------------------------------------------
SERVICE STATUS:  cron.service                    loaded          active          running
SERVICE STATUS:  ssh.service                     loaded          active          running
-------------------------------------------------------------------------------------------

我搜索如何从 3d 列中删除“.service”。

我尝试使用 substr($i, 0, -8) 和 ${1:-8}

有没有人知道如何从末尾去掉 8 个字符以使其看起来像这样:

-----------------------------------------------------------------------------------
SERVICE STATUS:  cron                    loaded          active          running
SERVICE STATUS:  ssh                     loaded          active          running
-----------------------------------------------------------------------------------

【问题讨论】:

  • systemctl list-units | grep $1 -> systemctl list-units $1
  • @KamilCuk,好点,但不是真正的等价
  • sed 's/\.service//'?
  • awk '{sub(".service","")}1'?

标签: bash awk printf


【解决方案1】:

当您使用 awk 时,您永远不需要 grep,因为 grep 'foo' file | awk '{print 7}' 可以写成 awk '/foo/{print 7}' file

而不是计算字符,只需删除从最后一个 . 开始的所有内容:

systemctl list-units |
awk -v tgt="$1" '
    {
        svc = $1
        sub(/\.[^.]*$/,"",svc)
    }
    svc == tgt {
        printf "SERVICE STATUS:  %-25s \t %s \t %s \t %s\n",svc,$2,$3,$4
    }
'

我还加强了您的比较,以避免在调用服务名称时出现错误匹配,该服务名称是某个其他服务名称的子集或包含像 . 这样的正则表达式元字符。

【讨论】:

  • 感谢您的快速回答。还要感谢关于“grep”和“awk”的建议——我会记住这一点。我花了 4 个小时完成这项任务,但我不知道如何解决它。
  • 我选择了您的解决方案,并遵循了您对响应后行为的建议。再次感谢您并致以最诚挚的问候!
【解决方案2】:

您需要根据字符串长度计算结束位置,考虑以下简单示例,让file.txt内容为

cron.service
ssh.service

然后

awk '{print substr($1,1,length($1)-8)}' file.txt

输出

cron
ssh

说明:substr 的参数是字符串,开始位置,结束位置,length 返回字符串中的字符数。

(在 gawk 4.2.1 中测试)

【讨论】:

  • 感谢您的解释。我之前试过这种方式:substr($1, length, -8),但没想到我应该指定一个应该计算字符数的变量。
  • @gacek length 在不使用 () 的情况下使用时只是在整行 ($0) 而不是特定字段中保存字符数的变量,例如,如果您的文件包含单行: 123 456 然后{print length} 给出7,因为它有 6 个数字和空格。
  • 关于length when used without () is just variable - 不,它仍然是一个函数调用,它只是length($0) 的简写。如果它是一个变量,那么除其他外,你可以给它赋值,但你不能。
【解决方案3】:

您可以在 awk 中使用gsub 函数,如下所示:

 systemctl list-units | grep 'cron' | awk '{gsub(".service","",$1); printf("SERVICE STATUS:  %-25s \t %s \t %s \t %s\n",$1, $2 ,$3,$4) }'
SERVICE STATUS:  crond                       loaded      active      running

【讨论】:

  • 1) gsub() 用于进行多次替换,而您只想执行 1,因此您应该改用 sub(),2) 任何 *sub() 函数的第一个参数是正则表达式,不是字符串,所以你应该使用正则表达式/.../,而不是字符串"...",分隔符,3)你应该用终止$来锚定你的正则表达式,这样你就删除了最后一个出现在行上,而不是第一个, 4) 你需要在正则表达式中转义. 否则它会匹配任何字符,而不仅仅是你想要匹配的.,5) 当你使用awk 时,你不需要grep,因为@987654333 @ = awk '/cron/{foo}'.
猜你喜欢
  • 2022-01-05
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
相关资源
最近更新 更多