You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用awk正确移除配置行中含单引号空格的最后字段?

问题与解决方案

问题

我有一份配置文件,示例行如下:

set system login user alice full-name 'Alice Example'
set system login user alice level admin

需要移除每行的最后字段。尝试用awk处理时遇到问题:

$ echo "set system login user alice full-name 'Alice Example'" | awk '{$NF=""; print}'
set system login user alice full-name 'Alice

该命令对单引号包裹的含空格最后字段无效;修改字段分隔符后结果仍不对:

$ echo "set system login user alice full-name 'Alice Example'" | awk -F "[ ']" '{$NF=""; print}'
set system login user alice full-name  Alice Example

请问错误出在哪?如何得到仅保留set system login user alice full-name的正确结果?

完整配置示例

set firewall all-ping enable
set firewall broadcast-ping disable
set firewall group port-group WebServices0xFF port 8080
set firewall group port-group WebServices0xFF port 8081
set firewall group port-group WebServices0xFF port 9090
set firewall group port-group WebServices0xFF port 9091
set firewall group port-group WebServices0xFF port 2006
set firewall group port-group WebServices0xFF port 2007
set firewall group port-group WebServices0xFF port 8000
set firewall group port-group WebServices0xFF port 10443
set firewall ipv6-receive-redirects disable
set firewall ipv6-src-route disable
set firewall ip-src-route disable
set firewall log-martians enable
set firewall receive-redirects disable
set firewall send-redirects enable
set firewall source-validation disable
set firewall syn-cookies enable
set interfaces bridge br1 address 10.12.34.100/24
set interfaces bridge br1 aging 300
set interfaces bridge br1 bridged-conntrack disable
set interfaces bridge br1 hello-time 2
set interfaces bridge br1 max-age 20
set interfaces bridge br1 priority 32768
set interfaces bridge br1 promiscuous disable
set interfaces bridge br1 stp false
set interfaces ethernet eth0 duplex auto
set interfaces ethernet eth0 poe output off
set interfaces ethernet eth0 speed auto
set interfaces ethernet eth0 vif 1100 bridge-group bridge br1
set interfaces ethernet eth1 duplex auto
set interfaces ethernet eth1 poe output 24v
set interfaces ethernet eth1 speed auto
set interfaces ethernet eth1 vif 1100 bridge-group bridge br1
set interfaces ethernet eth2 duplex auto
set interfaces ethernet eth2 poe output 24v
set interfaces ethernet eth2 speed auto
set interfaces ethernet eth2 vif 1100 bridge-group bridge br1
set interfaces ethernet eth3 duplex auto
set interfaces ethernet eth3 poe output 24v
set interfaces ethernet eth3 speed auto
set interfaces ethernet eth3 vif 1100 bridge-group bridge br1
set interfaces ethernet eth4 duplex auto
set interfaces ethernet eth4 poe output 24v
set interfaces ethernet eth4 speed auto
set interfaces ethernet eth4 vif 1100 bridge-group bridge br1
set interfaces ethernet eth5 duplex auto
set interfaces ethernet eth5 speed auto
set interfaces ethernet eth5 vif 1100 bridge-group bridge br1
set interfaces loopback lo
set interfaces switch switch0 mtu 1500
set interfaces wireguard wg0 mtu 1420
set interfaces wireguard wg0 peer 1syRMYD1jIVFMUMm5hF/j0MzjMQmuC5mlcT1VVugIkU= allowed-ips 172.27.0.0/24
set interfaces wireguard wg0 peer 1syRMYD1jIVFMUMm5hF/j0MzjMQmuC5mlcT1VVugIkU= allowed-ips 10.5.44.0/24
set interfaces wireguard wg0 peer 1syRMYD1jIVFMUMm5hF/j0MzjMQmuC5mlcT1VVugIkU= endpoint 'wireguard.example.org:51820'
set interfaces wireguard wg0 peer 1syRMYD1jIVFMUMm5hF/j0MzjMQmuC5mlcT1VVugIkU= persistent-keepalive 25
set interfaces wireguard wg0 peer 1syRMYD1jIVFMUMm5hF/j0MzjMQmuC5mlcT1VVugIkU= preshared-key wQ*obfuscated*X9/mf*obfuscated*yYM1/qcQeRow=
set interfaces wireguard wg0 private-key WG4ZY8OD*obfuscated*7mW*obfuscated*0+5qoZ28=
set interfaces wireguard wg0 route-allowed-ips true
set service gui http-port 81
set service gui https-port 10443
set service gui older-ciphers enable
set service lldp interface all
set service pppoe-server authentication local-users username test1gw1 password kh93BsG4
set service pppoe-server authentication local-users username test1gw1 static-ip 1.2.3.5
set service pppoe-server authentication mode local
set service pppoe-server client-ip-pool start 0.0.0.0
set service pppoe-server client-ip-pool stop 0.0.0.100
set service pppoe-server dns-servers server-1 9.9.9.9
set service pppoe-server dns-servers server-2 1.1.1.1
set service pppoe-server interface eth0
set service pppoe-server local-ip 1.2.3.4
set service snmp community o-obfuscated-f authorization ro
set service snmp contact someone@example.org
set service snmp location '1234, Teststreet 1'
set service ssh port 10
set service ssh protocol-version v2
set service unms disable
set system analytics-handler send-analytics-report false
set system crash-handler send-crash-report false
set system domain-name sub.example.org
set system host-name test-router
set system login banner post-login ''
set system login banner pre-login ''
set system login user alice authentication encrypted-password '$5$4*obfuscated*A$2*obfuscated*Q/.S*obfuscated*0/v*obfuscated*A'
set system login user alice authentication plaintext-password ''
set system login user alice authentication public-keys openpgp key AAAAB3N*obfuscated*
set system login user alice full-name 'Alice Example'
set system login user alice level admin
set system name-server 9.9.9.9
set system name-server '2001:4860:4860::8888'
set system name-server '2001:4860:4860::8844'
set system ntp server 0.ubnt.pool.ntp.org
set system ntp server 1.ubnt.pool.ntp.org
set system ntp server 2.ubnt.pool.ntp.org
set system ntp server 3.ubnt.pool.ntp.org
set system options reboot-on-panic true
set system syslog global facility all level notice
set system syslog global facility protocols level debug
set system syslog host 10.5.44.205 facility all level err
set system time-zone Europe/Vienna

错误原因

  1. 第一个awk命令用默认空格作为字段分隔符,会把'Alice Example'拆成'Alice和Example'两个字段,设置$NF=""后只会移除Example',留下'Alice,结果不符合预期。
  2. 第二个awk命令用[ ']作为分隔符,会把单引号和空格都当成字段分隔符,直接破坏了单引号包裹字段的结构,导致输出混乱。

解决方案

方法1:awk脚本(精准处理单引号)

这个脚本会跟踪单引号的状态,只把不在单引号内的最后一个空格作为字段分隔点,从而完整移除最后一个字段:

awk '{
    in_quote = 0
    last_space = 0
    for (i=1; i<=length($0); i++) {
        c = substr($0, i, 1)
        if (c == "'"") {
            in_quote = !in_quote
        }
        if (!in_quote && c == " ") {
            last_space = i
        }
    }
    if (last_space > 0) {
        print substr($0, 1, last_space-1)
    } else {
        print $0
    }
}' 你的配置文件名.txt

方法2:sed正则表达式

用sed的扩展正则匹配,跳过单引号内的内容,直接移除最后一个字段:

sed -E "s/(([^']*'[^']*')*[^']*)[[:space:]]+[^[:space:]]*$/\1/" 你的配置文件名.txt

验证效果

  • 处理set system login user alice full-name 'Alice Example',输出set system login user alice full-name
  • 处理set system name-server '2001:4860:4860::8888',输出set system name-server
  • 处理set system login banner post-login '',输出set system login banner post-login
  • 处理set interfaces loopback lo,输出set interfaces loopback

内容的提问来源于stack exchange,提问作者Christoph

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 02:30:50