V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
toyst
V2EX  ›  Linux

请教一下 shell 文本处理大神

  •  
  •   toyst · 2023-02-21 19:35:09 +08:00 · 2495 次点击
    这是一个创建于 644 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想把这段

    DEFAULT_PACKAGES += asdf asdf wfqw sdfg \
    jljldja ldoahf lajsdf \
    lj.msaldj jlasd-ewk
    
    $(eval $(call BuildTarget))
    
    xorrisofs -v 2>&1 | grep xorriso \
    

    替换成

    DEFAULT_PACKAGES += ghj65 dfg sfd \
    ljdfg sdlgjl \
    jsflj asda-sadf
    
    $(eval $(call BuildTarget))
    
    xorrisofs -v 2>&1 | grep xorriso \
    

    用 shell 怎么写啊

    14 条回复    2023-02-22 18:13:48 +08:00
    zhlxsh
        1
    zhlxsh  
       2023-02-21 19:43:08 +08:00 via iPhone
    没看出来啥规律,DEFAULT_PACKAGES 完全替换掉吗?或者说说你遇到啥问题了
    toyst
        2
    toyst  
    OP
       2023-02-21 20:04:04 +08:00 via Android
    @zhlxsh 就是替换 后面到$(eval 前面那一坨
    yang3121099
        3
    yang3121099  
       2023-02-21 22:01:27 +08:00
    可以使用 sed 命令对文本进行替换。假设这个文本存储在名为 text.txt 的文件中,可以使用以下命令:

    vbnet Copy code
    sed -i 's/asdf asdf wfqw sdfg \\/ghj65 dfg sfd \\/g; s/jljldja ldoahf lajsdf \\/ljdfg sdlgjl \\/g; s/lj.msaldj jlasd-ewk/jsflj asda-sadf/g' text.txt
    这个命令将对 text.txt 中的文本进行替换,并将结果写回到原文件。具体来说,使用 sed 命令的 -i 选项表示原地编辑,s/old/new/g 表示将 old 替换为 new ,\\ 表示换行符,多个替换操作用分号隔开。

    注意,为了避免误操作,请先备份原文件

    ————chatgpt
    boboliu
        4
    boboliu  
       2023-02-21 22:24:39 +08:00
    a="input"
    echo "${a/DEFAULT_PACKAGES \+\=*$/DEFAULT_PACKAGES += aa $'\n' bb $'\n\n'$}"

    多看 man
    boboliu
        5
    boboliu  
       2023-02-21 22:25:35 +08:00
    @boboliu #4 忘了插 // ,自己解决一下.jpg
    jackmod
        6
    jackmod  
       2023-02-21 22:27:52 +08:00   ❤️ 1
    sed -z
    以 0 作为行尾,替换 DEFAULT_PACKAGES += 和 $(eval 之间的部分即可
    boboliu
        7
    boboliu  
       2023-02-21 22:29:27 +08:00
    @boboliu #5 应该插 \\,另:bash only
    koebehshian
        8
    koebehshian  
       2023-02-21 22:53:04 +08:00
    可以利用 awk 和记录分隔符 RS 和 ORS 来替换;但最后一条记录不需要分隔符,所以改良了一下:
    把要替换的字符串设为输入记录分隔符 RS ,把输出记录分隔符 ORS 设为空,awk 遍历记录回调中,读取当前记录索引 FNR ,如果为 1 ,则输入$0 和要替换的字符串,否则只输出$0
    listenerri
        9
    listenerri  
       2023-02-21 23:13:01 +08:00
    ```
    #!/bin/bash

    # 从以 DEFAULT_PACKAGES 开头的行开始,
    # 直到以非反斜杠结束的行为止,将其替换为指定内容
    sed '/^DEFAULT_PACKAGES.*/,/.*[^\\]$/c \
    DEFAULT_PACKAGES += ghj65 dfg sfd \\\
    ljdfg sdlgjl \\\
    jsflj asda-sadf' test.txt

    # 命令假设待处理文件名为 test.txt

    ```
    listenerri
        10
    listenerri  
       2023-02-21 23:16:58 +08:00
    @listenerri #9 如果需要直接修改目标文件,为 sed 命令增加 -i 参数
    pagxir
        11
    pagxir  
       2023-02-21 23:38:00 +08:00   ❤️ 2
    cat << "EOF" |
    DEFAULT_PACKAGES += asdf asdf wfqw sdfg \
    jljldja ldoahf lajsdf \
    lj.msaldj jlasd-ewk

    $(eval $(call BuildTarget))

    xorrisofs -v 2>&1 | grep xorriso \
    EOF
    sed '/DEFAULT_PACKAGES/{:l; N; /\\/{s#\\\n#@#g; bl;}}'
    Owenjia
        12
    Owenjia  
       2023-02-21 23:54:36 +08:00
    简单写了下,假设原文本保存在 testdata 中,使用 sed 匹配起始行,然后循环读取,直到读到空行,再匹配字符进行替换,将输出的文件重定向到新文件即可:

    sed -n '/^DEFAULT_PACKAGES / { h; :loop; n; H; s/^$//; T loop; x; s/+= .*$/+= ghj65 dfg sfd \\\nljdfg sdlgjl \\\njsflj asda-sadf\n/};p' testdata > newdata
    drwx
        13
    drwx  
       2023-02-22 10:37:59 +08:00
    @jackmod 原来 sed 也有类似`find -print0`这样的选项啊,第一次知道,学到了,感谢!

    原来也很头疼 sed 处理跨行的文本,网上搜到的方法要不就是要用 sed 的 hold space, pattern space 来操作,要不就是 awk 写一大片处理逻辑,用 sed -z 就方便多了。

    @toyst 我给个具体的语句:

    ```bash
    sed -z -i -e 's@asdf asdf wfqw sdfg \\\njljldja ldoahf lajsdf \\\nlj.msaldj jlasd-ewk@ghj65 dfg sfd \\\nljdfg sdlgjl \\\njsflj asda-sadf@' a.txt
    ```
    yiyu1211
        14
    yiyu1211  
       2023-02-22 18:13:48 +08:00
    awk '/DEFAULT_PACKAGES/{print("DEFAULT_PACKAGES += ghj65 dfg sfd \\");getline;print("tljdfg sdlgjl \\");getline;print("tjsflj asda-sadf");next} 1' text.txt
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5472 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 07:20 · PVG 15:20 · LAX 23:20 · JFK 02:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.