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 / 问题 / 727352
Accepted
Kes
Kes
Asked: 2022-12-06 01:54:59 +0800 CST2022-12-06 01:54:59 +0800 CST 2022-12-06 01:54:59 +0800 CST

在文本文件 (XML) 中交换包含换行符的字符串的脚本

  • 772

我正在使用几周前更新的 Arch。包是使用是

  • 拱门 6.0.10-arch2-1
  • BASH 5.1.16(1)-发布
  • gnu sed 4.9
  • gnu grep 3.8
  • 打开盒子 3.6.1

在我的 Openboxrc.xml文本文件中,我有两行如下

<!-- <keybind key="Right"> -->

<keybind key="s-Up">

我希望使用脚本经常将上面两行切换/交换为下面两行

<!-- <keybind key="s-Up"> -->

<keybind key="Right">

rc.xml这使我能够快速更改键绑定,而无需每次都繁琐地编辑我的键绑定设置文本文件 ( )。

到目前为止,我的脚本在下面,但无法正常工作,尽管我知道它很接近。

我不太在意这种切换是如何实现的,但是已经花了很多时间在这上面,让下面的脚本工作会很好。

下面的sed表达式按预期进行文本交换。

如果满足条件,该if语句似乎会进行第一次sed交换,但如果不满足条件,则不会进行第二次sed交换,这就是问题所在。

var_a=""

#var_a=$(grep -zoP  "<\!\-\- <keybind key=\"Right\"> \-\->\n\n<keybind key=\"s-Up\">" /home/kes/Dropbox/lubuntu-rc.xml | sed ':a;N;$!ba;s|\n\n||g')

var_a=$(grep -zoP  "<\!\-\- <keybind key=\"Right\"> \-\->\n\n<keybind key=\"s-Up\">" /home/kes/Dropbox/lubuntu-rc.xml | tr -d '\n' )

# result of grep is
# <!-- <keybind key="Right"> --><keybind key="s-Up">

echo $var_a; sleep 0.5

#if [[ -z ! "$var_a" ];then
if [[ '$var_a'=='<!-- <keybind key="Right"> --><keybind key="s-Up">' ]]; then

   sed -ie ':a;N;$!ba;s|<!-- <keybind key="Right"> -->\n\n<keybind key="s-Up">|<!-- <keybind key="s-Up"> -->\n\n<keybind key="Right">|g' /home/kes/Dropbox/lubuntu-rc.xml

else

   sed -ie ':a;N;$!ba;s|<!-- <keybind key="s-Up"> -->\n\n<keybind key="Right">|<!-- <keybind key="Right"> -->\n\n<keybind key="s-Up">|g' /home/kes/Dropbox/lubuntu-rc.xml

fi
text-processing
  • 2 2 个回答
  • 39 Views

2 个回答

  • Voted
  1. Best Answer
    Philippos
    2022-12-06T02:14:32+08:002022-12-06T02:14:32+08:00

    实际上,永远不会满足条件,因为单引号'$var_a'会阻止您的变量完全展开,因此文字字符串$var_a永远不会等于其他文字字符串。

    使用双引号,它应该可以工作,但我想对您的脚本添加一些评论:

    (1)你首先做一个grep,然后基于你从中得到的内容的条件grep,最后使用两个不同的sed脚本。这很可能会导致错误。实际上,您sed将独自完成整件事:

    sed -ie ':a;N;$!ba
      s|<!-- <keybind key="Right"> -->\n\n<keybind key="s-Up">|<!-- <keybind key="s-Up"> -->\n\n<keybind key="Right">|g
      t
      s|<!-- <keybind key="s-Up"> -->\n\n<keybind key="Right">|<!-- <keybind key="Right"> -->\n\n<keybind key="s-Up">|g' \
      /home/kes/Dropbox/lubuntu-rc.xml
    

    如果进行了第一个替换,则t跳转到脚本末尾,否则执行另一个替换。和已经包含在内grep!if

    (2)你收集所有行的方法:a;N;$!ba只适用于 GNU sed,因为根据 POSIX 标准,冒号后的所有内容都是跳转标记,也不例外;。对你来说没问题,因为你有 GNU sed,但你也可以-z选择在没有零件的情况下一次运行处理孔文件。如果你喜欢它便携,H;1h;$!d;x通过保持空间做同样的事情。

    (3)我认为,global 标志是多余的,因为那些线只存在一次,对吗?

    (4)一遍又一遍地写同样的东西,可能会导致错误并且更难阅读。为什么不通过标记\(\)并引用它来重用一个零件\1呢?

    sed -iz 's|<!-- \(<keybind key="\)Right"> -->\n\n\1s-Up">|<!-- \1s-Up"> -->\n\n\1Right">|
      t
      s|<!-- \(<keybind key="\)s-Up"> -->\n\n\1Right">|<!-- \1Right"> -->\n\n\1s-Up">|' \
      /home/kes/Dropbox/lubuntu-rc.xml
    

    (5)其实不需要把整个文件当成一个文件来处理(对于大文件甚至会造成溢出),只需要将连续的每三行一起处理,使用N;P;Dscheme(一般是两行一起,添加1N到将其扩展为三行):

    sed -i '1N;N
      s|<!-- \(<keybind key="\)Right"> -->\n\n\1s-Up">|<!-- \1s-Up"> -->\n\n\1Right">|
      t
      s|<!-- \(<keybind key="\)s-Up"> -->\n\n\1Right">|<!-- \1Right"> -->\n\n\1s-Up">|;
      P;D' /home/kes/Dropbox/lubuntu-rc.xml
    

    人们可能会进一步简化这一过程,但这需要有关文件内容的额外信息。

    • 1
  2. Kusalananda
    2022-12-06T06:05:33+08:002022-12-06T06:05:33+08:00

    假设 XML 文档格式正确且句法正确,您可以使用 XML 处理器xmlstarlet来切换值。

    忽略文档中注释掉的 XML,下面通过首先将每个节点的所有key属性从值更改为(具有其他值的属性不会受到影响)来实现此目的。然后它将相同的属性从更改为,最后从更改为。该字符串是一个任意字符串,否则不用于节点的属性。keybindRighttemporarys-UpRighttemporarys-Uptemporarykeykeybind

    这有效地交换了从Right到的值,s-Up反之亦然。

    xmlstarlet edit \
        --var attr '//keybind/@key' \
        --update '$attr[.="Right"]'     --value temporary \
        --update '$attr[.="s-Up"]'      --value Right \
        --update '$attr[.="temporary"]' --value s-Up \
       file.xml
    

    这将把一个文件变成像

    <?xml version="1.0"?>
    <root>
      <keybind key="s-Up"/>
      <keybind key="s-Down"/>
      <keybind key="Right"/>
    </root>
    

    ... 进入

    <?xml version="1.0"?>
    <root>
      <keybind key="Right"/>
      <keybind key="s-Down"/>
      <keybind key="s-Up"/>
    </root>
    

    如果--inplace直接在edit命令行中的单词后插入,编辑将就地进行,修改原始文件。

    • 1

相关问题

  • grep 从 $START 到 $END 的一组行并且在 $MIDDLE 中包含匹配项

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

  • 在awk中的两行之间减去相同的列

  • 多行文件洗牌

  • 如何更改字符大小写(从小到大,反之亦然)?同时[重复]

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