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 / 问题 / 758329
Accepted
Rafiq
Rafiq
Asked: 2023-10-07 11:13:05 +0800 CST2023-10-07 11:13:05 +0800 CST 2023-10-07 11:13:05 +0800 CST

在文本文件中同一字符串的开头用 $ 符号替换任何 <> 闭合字符串

  • 772

我有一些文件驻留在 Linux 系统上,其中包含一些占位符,例如下面的文件:

测试.txt:

This is a line with <VARIABLE1>@<VARIABLE2>.
This is a line with <VARIABLE3>.
This is a line with <VARIABLE_UNKNOWN>.
This is another line contains a<b.

我想更改此文件,如下所示:

This is a test line with $VARIABLE1@$VARIABLE2.
This is a test line with $VARIABLE3.
This is a test line with $VARIABLE_UNKNOWN.
This is another line contains a<b.

请注意,所有这些以 结尾的变量<>仅包含大写字母、数字和下划线。

我本可以使用以下方法,但a<b变成了a$b。

file_contents=$(<$file_path)
file_contents=${file_contents//</$}
file_contents=$(echo "$file_contents" | tr -d '>')
echo "$file_contents" > test.txt

我试图避免sed使用变得非常难以调试的复杂命令。我怎样才能实现这个目标?

text-processing
  • 4 4 个回答
  • 229 Views

4 个回答

  • Voted
  1. terdon
    2023-10-07T17:33:14+08:002023-10-07T17:33:14+08:00

    如果问题可以表述为“我想转换所有包含在其中< >且仅由一个或多个大写字母、数字和下划线组成的字符串,这些字符串包含在它们< >自身中,但用 a$代替< >”,那么您可以这样做:

    $ perl -pe 's/<([A-Z\d_]+)>/\$$1/g' file 
    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    这-pe意味着“逐行读取输入文件,应用给出的脚本-e,然后打印每一行”。然后,我们将替换运算符 ( s/OLD/NEW/) 与g标志一起使用,以便它替换该行中的所有匹配项。最后,正则表达式查找<后跟一个或多个(指+一个或多个)大写 ASCII 字母 ( A-Z)、ASCII1 十进制数字 ( \d) 或_以 结尾的下划线 ( ) >。现在,因为模式位于括号 ( ) 中,所以我们已“捕获”它并可以在替换中([A-Z\d_]+)引用它。$1因此,我们将匹配的内容替换为 a $(需要转义为\$),然后替换匹配的内容:\$$1。


    至少只要$PERL_UNICODE未设置环境变量,在这种情况下它就可以匹配其他类型的十进制数字。使用该a标志给s///操作符保证只有0123456789被匹配,或者替换\d为0-9or0123456789

    • 2
  2. Best Answer
    Ed Morton
    2023-10-07T20:39:18+08:002023-10-07T20:39:18+08:00

    由于这是对各行的简单替换,因此执行此操作的 sed 命令并不复杂:

    $ sed -E 's/<([[:upper:][:digit:]_]+)>/$\1/g' file
    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    或者如果您的 sed 没有-E任何 POSIX sed:

    sed 's/<\([[:upper:][:digit:]_]\{1,\}\)>/$\1/g' file
    

    如果您的 sed 甚至不兼容 POSIX,那么请获取一个新的,但对于这一特定的事情您可能会这样做:

    sed 's/<\([A-Z0-9_][A-Z0-9_]*\)>/$\1/g' file
    

    正如@chrisdavies 指出的那样,这可能不是您真正应该尝试获得的输出,因为它会变成,<VAR1>27您$VAR127应该真正瞄准其中任何一个:

    $ sed -E 's/<([[:alnum:]_]+)>/${\1}/g' file
    This is a line with ${VARIABLE1}@${VARIABLE2}.
    This is a line with ${VARIABLE3}.
    This is a line with ${VARIABLE_UNKNOWN}.
    This is another line contains a<b.
    

    $ sed -E 's/<([[:alnum:]_]+)>/"${\1}"/g' file
    This is a line with "${VARIABLE1}"@"${VARIABLE2}".
    This is a line with "${VARIABLE3}".
    This is a line with "${VARIABLE_UNKNOWN}".
    This is another line contains a<b.
    

    取决于您计划如何处理该输出。

    FWIW 通常,当人们在文本中包含占位符字符串时,他们不会将其替换为shell 变量的名称,而是将其替换为shell 变量的内容,否则当您可以刚刚创建文本时,在文本中使用占位符有什么意义首先使用 shell 变量名称?

    • 2
  3. jubilatious1
    2023-10-10T06:08:29+08:002023-10-10T06:08:29+08:00

    使用Raku(以前称为 Perl_6)

    ~$ raku -pe 's:g/ \< ( <[A..Z0..9_]>+ ) \> /\$$0/;'  file
    

    再说一遍,这几乎是 @terdon 优秀 Perl 答案的直接翻译。

    在乐,

    1. 正则表达式修饰符(例如global)位于匹配器的开头,前面带有冒号,以给出s:g///“替代全局”形式。
    2. <[ ... ]>在识别域内,使用尖括号包围的方括号创建自定义字符类。方括号单独用于将正则表达式原子和/或属性分组在一起(参见底部的示例)。
    3. 字符范围用..双点指定,如 (例如)A..Z或0..9。
    4. Raku 简化了转义规则,使得所有非字母数字非下划线字符必须加引号或(反斜杠)转义才能被理解为正则表达式中的文字,因此需要在识别域中使用and \<。\>
    5. 编号捕获在 Raku 中通过括号指定(与 Perl 中相同),但是这些编号捕获从替换域开始$0并且必须在替换域中使用。
    6. OP 指的是错误的替换,并且通常要求反斜杠某些字符可能会出现问题。为了提供帮助,Raku 允许{...}在替换域中使用代码块,以便可以编写上述替换{"\$$0"}(即内插字符串)。对于在输出中执行简单的数学运算(求和等)非常有用。

    输入示例:

    This is a line with <VARIABLE1>@<VARIABLE2>.
    This is a line with <VARIABLE3>.
    This is a line with <VARIABLE_UNKNOWN>.
    This is another line contains a<b.
    

    示例输出:

    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    最后,@terdon 很好地概述了所有正则表达式系统的问题,因此需要准确理解 digital 的含义,即这些数字是 ASCII 数字还是 Unicode 数字?

    Raku 以其成为“Unicode 就绪”语言而自豪,您可以在底部的第一个链接中找到用于 Raku 正则表达式的 Unicode 字符类的广泛列表。因此,在 Raku 中,\d数字简写包括 Unicode 数字。您可以按照上面的方式枚举数字,或者使用字符类与连词组合将数字0..9子集/限制\d为 ASCII 数字,如下所示:<:ASCII>&&[<:ASCII> && \d]

    ~$ raku -pe ' s:g/ \< ( [ [<:ASCII> && \d] | <:Lu> | _ ]+ ) \> /\$$0/;'  file 
    

    上面<:Lu>是“Letters-uppercase”的 Unicode 字符类。如果需要,<:ASCII>可以使用相同的技巧来子集为“ASCII 字母大写”(或更简单地,重新排列上面的方括号以重新组合)。

    https://docs.raku.org/language/regexes#Unicode_properties
    https://www.unicode.org/terminology/digits.html
    https://docs.raku.org/language/regexes#Conjunction:_&&
    https:// /docs.raku.org/language/regexes
    https://raku.org

    • 0
  4. Prabhjot Singh
    2023-10-10T20:11:38+08:002023-10-10T20:11:38+08:00

    使用gawk:

    $ awk '{print gensub(/<([[:alnum:]_]+)>/, "$\\1", "g")}' file
    # Or
    
    $ awk '{print gensub(/<(\w+)>/, "$\\1", "g")}' file
    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    在 gensub() 函数中,可以使用括号 as 来记忆子模式,并在稍后使用ascaptured group引用它。backreference\n

    来自GNU awk手册:

    gensub()提供了sub()或gsub()中不提供的附加功能:能够在替换文本中指定正则表达式的组件。这是通过在正则表达式中使用括号来标记组件,然后在替换文本中指定“\N”来完成的,其中N是 1 到 9 之间的数字。

    • 0

相关问题

  • 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