我正在尝试从可能随时间变化的长字符串中提取一个值。例如,字符串可能看起来像这样
....../filename-1.9.0.3.tar.gz"<....
我想要提取的是之间的值文件名-和.tar.gz,本质上是文件版本(在本例中为 1.9.0.3)。我需要这样做的原因是因为我稍后可能会运行该命令,并且该值将是 1.9.0.6 或 2.0.0.2 或完全不同的值。
我怎样才能做到这一点?我目前只使用 grep,但我不介意使用其他实用程序,例如 sed 或 awk 或 cut 等。为了完全清楚,我只需要提取字符串的文件版本部分,因为它很长(两侧),其他所有内容都需要以某种方式删除。
答案1
对于grep -P
/ pcregrep
,使用正向后视和正向前视:
grep -P -o '(?<=STRING1).*?(?=STRING2)' infile
在你的情况下替换STRING1
为filename-
和STRING2
\.tar\.gz
如果您无权访问pcregrep
和/或如果您grep
不支持,-P
您可以使用您最喜欢的文本处理工具来完成此操作。这是一种可移植的方式,可以为ed
您提供相同的输出:
ed -s infile <<\IN
g/STRING1/s//\
&/g
v/STRING1.*STRING2/d
,s/STRING1//
,s/STRING2.*//
,p
IN
它是如何工作的:在每个出现的地方添加一个换行符STRING1
(所以现在每行最多出现一次),然后STRING1.*STRING2
删除所有不匹配的行;对于其余的,我们只保留 和 之间的内容STRING1
并STRING2
打印结果。
答案2
为了那些没有 POSIX 系统的人的利益grep -P
,您可以使用任何 POSIX 系统sed
或awk
在任何 POSIX 系统上执行此操作。
sed -n -e 's/^.*\/filename-\([^\/]*\)\.tar\.gz.*$/\1/p' -e T -e q
说明:关闭默认打印,找到包含所需模式的行,并替换除要保留的部分之外的所有内容,打印替换结果,如果匹配则退出。请注意,如果第一个匹配行上有多个匹配项,则会选取最后一个匹配项。
使用 awk(选择该行的第一个匹配项):
awk 'match($0, /filename-[^/]*\.tar\.gz/) {
print substr(RSTART + 9, RSTART + RLENGTH - 9 - 6, $0);
exit;
}'