输入文件的每一行都将匹配其中一种模式:
"SCnnnn"
"SC-nnnn"
"SC_nnnn"
(n = [0-9],SC是文字的,但可以是大写或小写,最后会有1-4个数字,最后用字母数字,空格或其他非数字字符分隔)
该行的某处还会有一个文件扩展名(匹配“.abc”),其中abc = upper | lower字母数字在任何位置。
我想提取第一个模式并将其与每行的解压缩文件扩展名一起打印。这就是我到目前为止所做的:
sed -E -n 's/([Ss][Cc][-_]*[0-9][0-9]*).*(\.[a-zA-Z0-9]{3})/\1\2/p' infile
这是一个示例输入行:
SCSCSCSCSCSCSCSCSC1867SCBrSCSCSCSC&SCBlSCkSCSCBSCrSCbSCckSC.xyz
所需的输出为:
SC1867.xyz
但我得到的是:
SCSCSCSCSCSCSCSCSC1867.xyz
有人可以告诉我为什么这会在我想要的部分之前返回“SC”吗?我知道这与贪婪有关,但我无法理解它。
(一切正常,我的“SCnnn”匹配位于该行的开头。)
我对其他工具持开放态度 - 例如awk - 如果他们提供更直接的解决方案。
编辑:我认为我找到了一个解决方案 - 至少看起来有效:sed -E -n 's/.*([Ss][Cc][-_]*[0-9][0-9]*).*(\.[a-zA-Z0-9]{3})/\1\2/p'
答案 0 :(得分:0)
这实际上不一定是在这里发挥作用的贪婪。发生这种情况的原因是因为sed正在替换一行的一部分,然后打印整行(p
命令的后缀s//
执行此操作)。
为了更清楚地了解发生了什么,make infile
包含一个更明显的字符串,如0o0o0o0o0o0o0o0oSC1867lalalalalalfalalala.xyz
并运行您的第一个命令。以下是结果
[user@localhost ~]$ sed -E -n 's/([Ss][Cc][-_]*[0-9][0-9]*).*(\.[a-zA-Z0-9]{3})/\1\2/p' infile
0o0o0o0o0o0o0o0oSC1867.xyz
作为一个慢动作:sed在0o0o0
之后找到你的[Ss] [Cc]字符,并尽职尽责地用你想要的替换代替你描述的字符串;即,它保持SC_
- 类似的部分和四位数,然后删除数字后的所有内容,直到后缀。当p
命令打印出部分更改的行时,会出现此问题,包括所有不需要的 0o ze。
作为替代解决方案,不涉及打印部分更改的行,而是匹配整行并将其更改为您的目的,以下命令为包含示例字符串的文件提取了stdout的正确答案:
[user@localhost ~]$ sed -e 's/^.*\([Ss][Cc][-_]\?[0-9]\{4\}\).*\(\.[a-Z]\{3\}\)$/\1\2/' infile
SC1867.xyz
将该正则表达式向下打破:正则表达式从行的开头(^
)开始,消耗所有字符(.*
),直到它看到SC(上部或下部,{{1然后它检查一个可选的连字符或下划线([Ss][Cc]
),后面跟着正好四位数([-_]\?
)。然后,所有字符都被消耗,直到看到一个点([0-9]\{4\}
),然后是正好三个字母数字字符(\.
)和一个行尾([a-Z]\{3\}
)。通配符未使用的两个表达式将保存到寄存器并连接($
)。
... \1\2
也适用,如果你不像我一样喜欢反斜杠。