【问题标题】:multiline sed to extract string terminated by a single quote多行 sed 提取以单引号结尾的字符串
【发布时间】:2012-08-29 13:13:08
【问题描述】:

我有许多 M4 宏文件,如果存在,我希望从中提取单个文件路径实例。

每个文件只有一行

define(`XSETROOT', `some_command with parameters SOME_DIR/subdir1/subdir2/filename')

或分布在两行

define(`XSETROOT', dnl
`some_command with parameters SOME_DIR/subdir1/subdir2/filename')

或根本没有条目。

所以我希望找到开始的行

define(\`XSETROOT',

然后从同一行或下一行提取以“空格”和“单引号”为界的字符串,即

SOME_DIR/subdir/subdir/filename

这是否可以在不使用多个 sed 调用的情况下完成?

附加信息(下面评论字段中的格式似乎不起作用)--

在最简单的情况下,当所有内容都在同一行时,引号的问题可以通过适当的引用/取消引用来克服,并且这个表达式有效

sed -ne 's|define(`XSETROOT'\'',.*`.* \(.*\)'\''.*|\1|p' file.m4

更多信息--

感谢 MvG 的响应展示了如何进行多行处理,当数据分成两行时,此表达式有效

sed -ne '/define(`XSETROOT/{n;s|`.* \([^'\'']*\)'\'').*|\1|p}' file.m4

但问题仍然存在,是否有可能构造一个表达式来处理一两行上的数据,或者我是否必须尝试其中一个来查看是否有返回的字符串,如果没有则尝试另一个看看它是否返回一个字符串?

【问题讨论】:

  • 我知道该怎么做,但是处理所有这些不同的报价简直是要了我的命。由于这个原因,我无法让我的命令工作:(
  • 在所有内容都在同一行的情况下,这可以解决单引号问题
    sed -ne 's|define(XSETROOT'\'',.*.* (.*) '\''.*|>\1 所以我需要帮助的部分是如果可能的话,如何在同一行或下一行处理一次调用

标签: sed


【解决方案1】:

试试这个:

sed -n "/define(\`XSETROOT'/{/dnl/N;s/.* //;s/'.*//;p}"
  • 除非当前行包含define(`XSETROOT',否则什么都不做。
  • 如果该行还包含dnl,则追加下一行。
  • 删除所有内容,直到最后一个空格。
  • 删除最后一个单引号后的所有内容。
  • 打印剩余的字符串。

N 命令限制为实际存在dnl 的情况有两个目的:它允许在文件末尾匹配单行定义,并允许两个后续定义,其中第一个仅占一行。

【讨论】:

  • 该表达式中有些地方不太正确,因为它导致打印出“dnl”而不是文件名字符串。
  • 奇怪,如果适用于我和我的 GNU sed 4.2.1。你可以删除s/// 命令,看看这是否会导致两行都被打印?
  • sed --version GNU sed 版本 4.2.1 因此尝试使用包含在两个单独行中的文件定义(XSETROOT', dnl hsetroot -tile FVWM_DIR/themes/Crystal/Plaster-Pale_Blue.jpg') dnl 使用sed -n "/define(`XSETROOT'/{/dnl/N;}" $X11_DIR/share/fvwm/themes/Crystal/Theme.m4 根本不产生任何输出。
  • 删除 -n 会导致整个文件被输出。
  • 删除s/// 时,不要删除p,因为这是打印结果。所以试试sed -n "/define(\`XSETROOT'/{/dnl/N;p}" 看看是否打印了两行。
【解决方案2】:

如果您可以使用awk,它可能对您有用:

awk -F "[`']" 'BEGIN { RS=")" } { print gensub(".* ","","g",$4) }' INPUTFILE

请参阅(几乎相同 - 因为 Ideone.com 不支持 CLI 参数)in action here

解释:

  1. -F "[`']" 将字段分隔符设置为 [`'] 的正则表达式(这两个引号字符中的任何一个)
  2. RS=")" 设置记录分隔符,这样我们就可以拥有多行记录
  3. gensub(".* ","","g",$4) 返回第四个字段中最后一个空格后的所有内容

【讨论】:

  • 感谢您的回复,但我特别想了解如何使用 sed 执行此操作,因为我更喜欢使用 awk 来处理数据列而不是行编辑。
【解决方案3】:

正确的解决方案是使用 M4 本身。

m4 -D XSETROOT='some suitable value with a/path/to/a/file' file.m4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    相关资源
    最近更新 更多