【问题标题】:sed in Vista - how to delete all symbols between?Vista中的sed - 如何删除之间的所有符号?
【发布时间】:2010-09-30 08:45:14
【问题描述】:

我有一个 bat 文件,我应该用它来删除一个文件的一部分并保存到另一个文件中。我需要删除文本“[aaa bbb]”和“[ccc ddd]”之间的所有符号。那就是如果我有文字:

[aaa bbb]
1
2
3
[ccc ddd]

我应该有输出:

[aaa bbb]
[ccc ddd]

谢谢

编辑:我想澄清这个问题。我应该删除marker1和marker2之间的所有符号。 Marker1 和 marker2 只是一些单词或文本的一部分,而不是强制性的行。例如我会:

[aaa bbb] [ccc]
1
2
3
4
5
[www yyy]

如果我想删除 [aaa bbb] 和 [www yyy] 之间的文本,我应该将其作为输出:

[aaa bbb] 
[www yyy]

【问题讨论】:

    标签: windows sed


    【解决方案1】:

    看看this sed hints page上的“在标记1和标记2之间删除”部分

    将其应用于您的示例。 clean.sed

    /^\[aaa bbb\]$/,/^\[ccc ddd\]$/{
     /^\[aaa bbb\]$/!{
       /^\[ccc ddd\]$/!d
     }
    }
    

    运行使用:

    sed -f clean.sed inputfile.txt
    

    要“就地”编辑输入文件,请使用 sed 的 -i 选项:

    sed -i.bak -f clean.sed datafile.txt
    

    在编辑原始文件之前保存名为“datafile.txt.bak”的文件的备份副本。

    编辑:由于假设标记总是在自己的一行上是错误的,这里有一个脚本可以处理一行中间的标记:

    /\[aaa bbb\]/,/\[ccc ddd\]/{
      s/\[aaa bbb\].*/[aaa bbb]/
      s/.*\[ccc ddd\]/[ccc ddd]/
      /\[aaa bbb\]$/!{
        /^\[ccc ddd\]/!d
      }
    }
    

    对于这个输入:

    foo[aaa bbb]1
    2
    3
    4
    5[ccc ddd]bar
    foo
    [aaa bbb]
    1
    2
    3
    [ccc ddd]
    bar
    

    它产生:

    foo[aaa bbb]
    [ccc ddd]bar
    foo
    [aaa bbb]
    [ccc ddd]
    bar
    

    注意!无法处理标记可以出现在同一行的文件。

    再次编辑:如果标记 1 的输入格式是这样的,您总是可以指望它在自己的一行上,您可以简化脚本:

    /^\[aaa bbb\]$/,/\[ccc ddd\]/{
      s/.*\[ccc ddd\]/[ccc ddd]/
      /^\[aaa bbb\]$/!{
        /^\[ccc ddd\]/!d
      }
    }
    

    (将标记 1 锚定在一行的开头和结尾,并跳过标记 1 行的修剪。)

    【讨论】:

    • 如何在bat文件中使用?我不知道如何使用多行命令。谢谢
    • 那是我写的 D:\tmp\sed.exe ...command 我可以在这里使用多行命令吗?
    • 将 sed 脚本放在它自己的文件中应该可以工作。 (sed -f)
    • 我更新了答案。让我知道它是否有效(我目前不在 Windows 上,因此无法检查。)
    • 在我看来它有效!但我还有一个问题。如果我只想在 marker1 之后删除 1 行而 marker1 是整行怎么办?
    【解决方案2】:
    D:\tmp\sed.exe -f sedscript.sed D:\tmp\test.txt >c:\tmp\test2.txt /^\[产品特点\]$/,/^\[Dm$/{ /^\[产品特点\]$/!{ /^\[Dm$/!d } }

    【讨论】:

    • 不,没有任何消息。它只是不会删除或者可能不会保存到输出文件中,我可以说得更准确
    • 我的意思是我不能说得更准确
    • 如果您在提示符下运行命令并跳过重定向到输出文件(如果输出足够多,则通过更多管道)您可以更快地调试它。
    •  D:\tmp>testbat.bat D:\tmp>D:\tmp\sed.exe -f sedscript.sed D:\tmp\test.txt 1>c:\ tmp\test2.txt 
      我不知道“1”符号来自哪里,我的脚本中没有它
    • 这真的很奇怪。并且 D:\tmp\test.txt 不为空? (我必须检查,对不起)。
    【解决方案3】:

    请注意,sed 可用于 Windows,以及其他 GNU 实用程序的 whole bunch。我不确定您是否要问是否有等效的工具,或者一旦您获得了该工具,该如何实际操作。

    【讨论】:

    【解决方案4】:

    如果您信任 this answer 的“类似 sed”的 VB 脚本...

    sed.vbs:

    Dim pat, patparts, rxp, inp
    pat = WScript.Arguments(0)
    patparts = Split(pat,"/")
    Set rxp = new RegExp
    rxp.Global = True
    rxp.Multiline = False
    rxp.Pattern = patparts(1)
    Do While Not WScript.StdIn.AtEndOfStream
      inp = WScript.StdIn.ReadLine()
      WScript.Echo rxp.Replace(inp, patparts(2))
    Loop
    

    您可以输入
    cscript /Nologo sed.vbs s/^\d+\s*$/ < in.txt(in.txt 是您的初始文本)

    你将获得预期的输出......

    ^\d+\s*$
    

    将定位以一位或多位数字开头的任何行,然后一行中的 0 个或多个空格。


    这不是最好的“纯 sed”解决方案,它实际上不能删除行,但这是一个原生的“符合 vista”的解决方案......


    实际上,以下故意解释“dsed-command”的黑客可以“删除”行:

    Dim pat, patparts, rxp, inp
    pat = WScript.Arguments(0)
    patparts = Split(pat,"/")
    Set rxp = new RegExp
    rxp.Global = True
    rxp.Multiline = False
    rxp.Pattern = patparts(1)
    Do While Not WScript.StdIn.AtEndOfStream
      inp = WScript.StdIn.ReadLine()
      out = rxp.Replace(inp, patparts(2))
      if not patparts(2)="d" or not out="d" Then
        WScript.Echo out
      end if
    Loop
    

    cscript /Nologo sed.vbs s/^\d+\s*$/ < in.txt 实际上会产生:

    [aaa bbb]
    [ccc ddd]
    

    在 .bat 中,您可以有一个 sed.bat:

    cscript /Nologo sed.vbs %1 < %2
    

    然后像这样执行那个.bat:

    C:\prog\sed>sed.bat s/^\d+\s*$/d in.txt
    

    【讨论】:

    • 我对“Vista 中的 sed”标题的阅读是“仅限 Vista 解决方案”,没有其他外部库/gnu 实用程序可以导入。如果这不是您所追求的,请编辑您的问题。
    • 由于它没有回答问题,我将其设为“社区 wiki”并将其留在那里以供存档。如果没有可用的“sed.exe”,它可以提供想法......
    • 确实如此。我不知道你可以像那样使用 vbs(好吧,我从来没有想过,我总是在 Windows 上使用 cygwin)。真的很高兴知道。
    • 注意。要打印的行与特定模式不匹配。需要匹配的是标记,删除它们之间的文本。
    【解决方案5】:

    我查看了 cmd 和 power shell - 找不到任何有用的东西。让自己成为 ActivePerl?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 2020-06-22
      • 2017-07-31
      • 2016-09-28
      • 1970-01-01
      相关资源
      最近更新 更多