【问题标题】:Ignore spaces, tabs and new line in SED忽略 SED 中的空格、制表符和换行符
【发布时间】:2016-06-23 14:32:11
【问题描述】:

我尝试替换包含制表符和换行符的文件中的字符串。 shell 文件中的命令如下所示:

FILE="/Somewhere"
STRING_OLD="line 1[ \t\r\n]*line 2"
sed -i 's/'"$STRING_OLD"'/'"$STRING_NEW"'/' $FILE

如果我手动删除换行符和制表符并只留下空格,那么我可以成功替换文件。但是如果我留下换行符,那么SED 将无法找到$STRING_OLD 并且无法替换为新字符串

提前致谢

科比

【问题讨论】:

  • 您的问题的详细信息表明您最多需要在整个文件中执行一次替换。这确实是您需要的吗?
  • 您的文件有多大?线可以多长?既然您使用的是 Linus,那么假设 GNU sed 的解决方案是否可以接受,或者您是否需要仅依赖 POSIX sed 功能的解决方案?
  • edit 你的问题要包括简洁、可测试的样本输入和预期输出,或者充其量你会得到你想要的,而不是你真正需要的。

标签: linux bash sed


【解决方案1】:

sed 一次读取一行,通常在读取行时也一次处理一行。但是,sed 确实具有读取附加行和对组合结果进行操作的功能。有几种方法可以应用于您的问题,例如:

FILE="/Somewhere"
STRING_OLD="line 1[ \t\r\n]*line 2"
sed -n "1h;2,\$H;\${g;s/$STRING_OLD/$STRING_NEW/g;p}"

这或多或少地完成了您描述的手动操作:它连接文件的所有行(但保留换行符),然后一次对整个缓冲区执行替换。但是,这确实假设文件很短(如果总文件长度超过 8192 字节,POSIX 不需要它工作)或者您使用的是没有缓冲区大小限制的sed,例如 GNU sed。由于您标记了 Linux,我假设可以假设 GNU sed

详细说明:

  • -n 选项关闭行回显,因为我们保存所有内容并在最后将修改后的文本打印在一个块中。
  • 有多个sed 命令,用分号分隔,并用文字$ 转义字符(对于shell):
    • 1h:在处理输入的第一行时,将“保持空间”替换为模式空间的内容(即第一行,不包括换行)
    • 2,\$H: 在处​​理从第二行到最后一行的任何行时,在保持空间中添加一个换行符,然后是模式空间的内容
    • \${g;s/$STRING_OLD/$STRING_NEW/g;p}:在处理最后一行时,执行这组命令:将保持空间复制到模式空间中;全局执行替换;打印模式空间的结果内容。

这是更简单的方法之一,但如果您需要适应seds,而在缓冲区容量方面不如 GNU 的能力,那么还有其他方法可以解决。不过,那些开始变得丑陋了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    相关资源
    最近更新 更多