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 / 问题 / 744013
Accepted
xpt
xpt
Asked: 2023-04-25 20:51:42 +0800 CST2023-04-25 20:51:42 +0800 CST 2023-04-25 20:51:42 +0800 CST

sed:替换成功为条件

  • 772

我遇到了一个很好的使用 tosed做替换,并使用它的成功状态作为打印行的条件:

$ seq 3 | sed -n 's/2/B/ p'
B

我想知道是否可以扩展这种简短形式以执行更多操作。喜欢,

  • 仅当替换成功时才打印该行,但是
  • 在打印出来之前,我需要做更多的更换

那可能吗?我尝试了以下但失败了:

$ seq 3 | sed -n 's/2/B/ {p}'
sed: -e expression #1, char 8: unknown option to `s'
sed
  • 4 4 个回答
  • 52 Views

4 个回答

  • Voted
  1. Kusalananda
    2023-04-25T20:57:31+08:002023-04-25T20:57:31+08:00

    您可以用作/2/更复杂命令的地址:

    sed -n '/2/ { s/2/B/; /BB/d; p; }'
    

    对于至少包含一个的任何行2,这将替换第一次出现的2with B(在这种情况下,此替换也可以缩短为s//B/空正则表达式表示“使用最近匹配的表达式”的位置),然后丢弃该行,如果它现在包含子字符串BB。然后该行将被输出(如果它没有被丢弃)。其他行根本不会输出,因为-n.

    你也可以使用

    sed -e '/2/!d' -e 'other commands'
    

    这将删除所有不包含的行2,然后应用于other commands其余行。

    使用多个表达式,每个表达式都使用-e,是将一系列命令应用于输入流的标准方法sed。大多数当前的sed实现也理解用 分隔表达式;。GNUsed不必;在}.

    • 4
  2. Best Answer
    Stéphane Chazelas
    2023-04-25T23:06:06+08:002023-04-25T23:06:06+08:00

    p这是命令的标志sed,它不是p sed命令。

    要执行某些操作(除了p打印生成的模式空间或w将其写入文件,w作为另一个可能与s命令一起使用的标志)只有在进行了替换时,您才可以使用命令t(或TGNU 中的命令sed)如果有替换(如果没有 for ),则分支到某个标签(如果没有标签,则分支到末尾-T),所以你可以这样做:

    GNU 特定的:

    sed -n 's/2/B/;T;=;p;#and other commands if there were substitutions'
    

    这就像:

    substitute(the first occurrence of 2 with B in the pattern space)
    if (no substitution was made so far)
       goto(end)
    print-pattern-space
    print-input-line-number
    : end
    
    sed '
      s/2/B/;t more
      d
      :more
      p;=;#and other commands
    '
    

    或者您可以使用:

    sed -n '/regexp/ { s//replacement/; p; =; }'
    

    在使用空正则表达式的地方,就像在ed.

    • 3
  3. Ed Morton
    2023-04-25T22:24:52+08:002023-04-25T22:24:52+08:00

    如果你需要做除此之外的任何事情,s/old/new/你最好使用 awk 而不是 sed 以获得清晰度、健壮性、可移植性、可维护性等的某种组合:

    $ seq 3 | awk 'sub(/2/,"B")'
    B
    
    $ seq 3 | awk 'sub(/2/,"B") { sub(/B/,"foo"); print }'
    foo
    
    • 1
  4. bakunin
    2023-04-26T06:31:26+08:002023-04-26T06:31:26+08:00

    您可以使用“{ .... }”对命令进行分组。一般形式为:

    /<regexp>/ {
                 cmd1
                 cmd2
                 ...
               }
    

    这里的“cmd”是任何常规的 sed 命令,如“s/.../.../”,还有“p”、“q”等。将此视为适用于所有的“规则”匹配正则表达式的行。您还可以通过在正则表达式和左大括号之间使用感叹号来否定规则。在这种情况下,规则适用于所有不匹配正则表达式的行。

    下面是一个示例,它打印从脚本开始到第一个非注释行的所有仅注释行:

    sed '/^[[:blank:]]*#/ !{
                              q
                            }'
    

    所有以“#”开头的行都匹配规则,因此只打印出来(我们没有使用“-n”选项来抑制它)。第一行(实际上是所有行,但实际上只有第一行被处理)不匹配正则表达式触发简单退出 sed 的规则。

    但是还有另一种比使用规则更强大的方法:定义所谓的“标签”。使用类似于 GOTO 的命令分支到的符号位置。它是这样工作的:

    1) 无条件分支 sed 脚本的工作方式如下:读取第一行输入,然后对它应用所有 sed 命令,一个接一个(如果该行被更改,则进一步的命令将应用于该更改的行)直到最后一个命令到达。如果不使用“-n”选项,结果将打印到 . 只有这样,才会读取下一行输入并重新开始该过程,直到处理完最后一行输入。

    有一种方法可以更改命令应用于当前行的顺序:

    :

    这个命令本身什么都不做,但它可以被其他命令用来分支到这个地方。你可能还记得像 BASIC 这样的语言和它们的“goto”命令?这标记了一个标签,随后的“goto”-(like)-命令可以跳转到该标签。分支到先前定义的标签的无条件 sed 命令是

    b

    “b”代表“分支”。对应于您使用“:”命令定义的内容。如果省略标签,则执行分支到脚本末尾。

    这是一个例子:你得到一个程序,但不幸的是代码缩进是用制表符而不是空格完成的,你想改变它。显然,您只想更改任何代码前面的选项卡,而不是代码中可能需要的选项卡。las,正则表达式中没有直接用于此的设备,因此您必须自己实现它。该算法是:只要一行的形式是空格,后面跟着一个制表符,将第一个制表符更改为 8 个空格,然后在同一行上重复,直到没有制表符位于任何文本的前面。然后才打印该行。这种类似循环的结构是使用“:”和“b”命令设置的。请注意,我在这里使用 \b(空白)和 \t(制表符)来使不同类型的空白可读。

    sed ':start
         /^\b*\t/ {
                    s/^\(\b*\)\t/\1\b\b\b\b\b\b\b\b/
                    b start
                  }'
    

    2) 条件分支 现在,你知道如何设置标签和分支到它们还有一个更进一步的转折:你可以根据 s/.../.../ 命令在成功之前执行的分支到这样的标签(这意味着:它改变了一些东西)或没有。这样做的命令是:

    吨

    如果 s/../../- 命令之一在最后一行被读取或自上次执行 at 或 T 命令后成功替换,则分支到

    吨

    这是“t”的否定对应物。如果没有s-command 成功,它就会分支。

    这是一个简单的例子,它是如何工作的。它没有做任何特别有用的事情,但它显示了原理:sed 脚本只接受任何输入的第一行。如果第一个字符是“a”、“b”或“c”之一,则打印“YES”,否则打印“NO”。

    sed -n 's/^[abc]/x/
            t yes
            b no
            :no
            s/^.*$/NO/p
            q
            :yes
            s/^.*$/YES/p
            q'
    

    控制流程很简单:首先尝试替换,如果第一个字符是“a”、“b”或“c”,则将其更改为“x”。如果成功,分支命令“t yes”将分支到 lael“yes”,其中整行更改为“YES”并且 sed 退出(“q”命令)。如果此替换不成功,则传递“t”命令并执行“b”命令,跳转到“no”标签。

    尝试各种输入(echo "..." | sed <script>足够好)以查看其工作原理,然后将“t”命令更改为“T”并观察对结果的影响。

    • 1

相关问题

  • Linux grep文件1中的内容在文件2中[重复]

  • 如何在第三个逗号后用条件grep行

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

  • 如何改进这个字符转换脚本?

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

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