AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 790219
Accepted
vrms
vrms
Asked: 2025-01-27 20:18:20 +0800 CST2025-01-27 20:18:20 +0800 CST 2025-01-27 20:18:20 +0800 CST

awk - 如何打印 $5 之后的所有字段?

  • 772

我有类似以下的输出

  975  Jan/21 - 19:59:36 ### sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
  986  Jan/21 - 20:04:21 ### grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"

现在我想将每一行简化为之后的所有内容$5,这样我就可以得到实际的完整命令?

我想我可以做| awk {'print $6, $7, $8, $9, $10, $11'}......等等。但感觉太不科学了,不够灵活而且很丑。

有人能建议如何实现这一点吗,或者我awk一开始就走错了路?

awk
  • 10 10 个回答
  • 1512 Views

10 个回答

  • Voted
  1. icarus
    2025-01-27T21:40:16+08:002025-01-27T21:40:16+08:00

    示例数据看起来像是来自命令历史记录,可能是命令编号、日期、时间、序列,### 然后是命令。在示例数据中,所有内容看起来排列整齐,因此问题变成了“如何删除前 29 个字符?”。Awk 不应该是您的首选,因为您可能希望保留有多个空格的位置,这意味着 awk 将内容拆分为字段对您没有用。

    cut -c 30-
    

    是其中一种方法。第二种方法是观察是否存在固定字符串 ### ,并且在此之前没有#字符。因此,您可以使用正则表达式来匹配行首、零个或多个非字符#,然后匹配固定字符串并删除它们。这种方法的优点是,如果数据发生变化,例如,如果命令号变得太大以至于需要额外的列来存储值,则此程序不需要进行任何更改。

    sed 's/^[^#]*### //'
    

    如果您确实想使用 awk,您可以使用gsubawk 来执行相同操作。

    • 8
  2. Best Answer
    Fravadona
    2025-01-28T03:23:34+08:002025-01-28T03:23:34+08:00

    以下是使用 POSIX awk剪切第一个 之前的所有内容的方法: ### 

    awk 'match($0, / ### /) {print substr($0, RSTART+RLENGTH)}'
    

    注意:它还会丢弃不包含 ### 

    • 8
  3. Chris Davies
    2025-01-27T20:44:57+08:002025-01-27T20:44:57+08:00

    您可以使用sed,假设###不会在一行中出现多次:

    sed 's/^.* ### //'
    

    输出

    sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    
    • 6
  4. Gilles Quénot
    2025-01-27T20:45:47+08:002025-01-27T20:45:47+08:00

    使用Perl一行代码打印第 5 列之后的所有内容:

    perl -lane 'print join " ", @F[4..$#F]' file
    

    使用数组切片。

    使用-aswitch 时,默认情况下在数组中的Perl行为类似awk并按空格拆分@F。您还可以使用它-F来定义字段分隔符(可以是正则表达式)。

    • 5
  5. Stéphane Chazelas
    2025-01-28T16:58:35+08:002025-01-28T16:58:35+08:00

    通过grep支持-o(输出匹配部分)和-P(类似 perl 的正则表达式)的实现:

    grep -Po '\s+###\s+\K.*'
    

    <whitespace>###<whitespace>将打印每行中第一次出现之后的内容。

    grep -Po '^\s*(\S+\s+){5}\K.*'
    

    打印前 5 个空格分隔字段后面的所有内容。

    • 3
  6. Scottie H
    2025-01-29T04:03:30+08:002025-01-29T04:03:30+08:00

    更通用的答案,以防其他人对不同的数据集有类似的问题:

    awk '{$1=$2=$3=$4=$5="";$0=$0;print}' [path/to/data_file]
    

    第一部分,$1=$2=$3=$4=$5=""将前 5 个字段设置为空字符。这样做的缺点是awk仍然记得 id 有这些字段,因此print $0会在输出行前面留下空白。

    因此第二部分$0=$0去掉了前导和尾随的空格。

    然后第三部分print $0打印新的、缩短的行。

    • 3
  7. terdon
    2025-01-27T20:30:29+08:002025-01-27T20:30:29+08:00

    是的,你走错了方向awk。我的意思是,你可以在 awk 中做到这一点,我稍后会向你展示如何做到这一点,但还有另一个工具,cut它正是为此而设计的。如果你想打印从第 5 个到最后一个的所有字段,你可以这样做:

    cut -d ' ' -f 5-
    

    指示使用空格作为分隔符,因为默认使用 TAB。然后,用于指示它-d ' ' 要打印哪些字段,这里我们指示它从第 5 个字段开始打印直到末尾 ( )。cut ut-f5-

    现在,如果你的文件结构不太好,如果你可以使用一个或多个空格作为分隔符,那么 awk 会是更好的选择,但它更复杂。你可以这样做,例如:

    awk '{ line=$5; for(i=6;i<=NF;i++){ line=line OFS $(i)} print line}'
    

    但这仍然会改变空格的数量,例如:

    $ echo "a b c d e           f   g" | awk '{ line=$5; for(i=6;i<=NF;i++){ line=line OFS $(i)} print line}'
    e f g
    

    哪里cut不会:

    $ echo "a b c d e           f   g" | cut -d ' ' -f 5-
    e           f   g
    

    我相信您可以获得更优雅的 awk 解决方案,但实际上,cut这里是正确的工具。

    • 2
  8. Ed Morton
    2025-01-28T05:18:24+08:002025-01-28T05:18:24+08:00

    使用任何 POSIX awk:

    $ awk '{sub(/^[[:space:]]*([^[:space:]]+[[:space:]]+){5}/,"")} 1' file
    sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    

    或 GNU awk 用于\s/ \S:

    $ awk '{sub(/^\s*(\S+\s+){5}/,"")} 1' file
    sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    

    或 POSIX sed:

    $ sed 's/^[[:space:]]*\([^[:space:]]\{1,\}[[:space:]]\{1,\}\)\{5\}//' file
    sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    

    -E或者具有支持 ERE 选项的 sed (例如 GNU 和 BSD seds):

    $ sed -E 's/^[[:space:]]*([^[:space:]]+[[:space:]]+){5}//' file
    sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    

    或 GNU sed 用于-Eand \s/ \S:

    $ sed -E 's/^\s*(\S+\s+){5}//' file
    sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    
    • 2
  9. jmf7
    2025-01-31T08:35:17+08:002025-01-31T08:35:17+08:00

    awk '{for (i=6;i<=NF;i++) printf("%s%s",(i==6)? "":" ",$i); printf("\n"); } ' 文件.txt

    • 0
  10. jubilatious1
    2025-02-01T14:32:50+08:002025-02-01T14:32:50+08:00

    使用Raku(以前称为 Perl_6)

    ~$ raku -ne 'put .words[5..*];'  file
    
    #OR:
    
    ~$ raku -ne 'put .comb(/ \S+ /)[5..*];'  file
    

    上述 Raku 答案是为了补充 @GillesQuénot 发布的出色 Perl 答案而编写的。对于单行程序,Raku 简化了命令行标志的数量,同时添加了几个例程来补偿。

    • 命令-ne行标志指示 Raku 逐行执行代码而不自动打印(awk类似行为)。
    • 在第一个答案中,该.words例程的缩写$_.words意思是在空格处中断文本输入。
    • 在第二个答案中,该.comb例程用于全局选择/ \S+ /一个或多个非空白字符。
    • 使用索引结果元素.[5..*]然后使用它put来输出将导致打印所需的列/元素切片,默认以(单个)空格字符作为分隔符。
    • 使用put将自动添加 EOL 换行符。

    示例输入:

    975  Jan/21 - 19:59:36 ### sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    986  Jan/21 - 20:04:21 ### grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    

    示例输出:

    sed "/^#include_dir/a include_dir = 'conf.d'" /opt/db/data/efa_bauen_ni_14/postgresql.conf
    grep -l "^port = '5" /opt/db/data/postgres/efa_bauen_ni/conf.d/*.conf | xargs sed -i "s/port = '5/port = '6/"
    

    https://docs.raku.org
    https://raku.org

    • 0

相关问题

  • 根据第一个逗号之前的匹配删除重复行数

  • 在另一个文件之后逐行追加行

  • 如何删除两行之间的单行

  • 重新排列字母并比较两个单词

  • 多行文件洗牌

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve