我正在尝试用linux中的'sed'做一些简单的格式化工作,我需要使用正则表达式在第15个字符后修剪一个字符串,然后在末尾附加一个'...'。像这样:
before: this is a long string that needs to be shortened
after: this is a long ...
任何人都可以告诉我如何将其作为正则表达式编写,并且如果可能的话解释它是如何工作的,以便我可以更好地学习正则表达式?
答案 0 :(得分:17)
以下适用于我:
echo "This is a test with more than 15 characters" | sed "s/\(.\{15\}\).\+$/\1…/"
这里发生的是我们匹配任何字符(.
)15次({15}
)。我们捕获括号内匹配的文本。以下部分(.+$
)匹配所有其余部分,直到行尾。我们用括号内的任何内容(\1
)替换它,然后是双曲线省略号。
为了满足sed
的正则表达方言(BRE),我们必须逃避一些角色。
答案 1 :(得分:6)
解释Konrand Rudolph的答案,因为你要求解释(啊,正如我写的那样,Konrad也加了他自己的解释!)
sed "s/\(.\{15\}\).+$/\1…/"
\(
启动一个组 - 请求regexp引擎记住parens中的内容,并将第一个这样的组分配给\ 1,将第二个分配给\ 2等。我们只需要\ 1这里
.
匹配任何内容......
\{15\}
...... 15次。
\)
结束小组。所以\ 1将包含前15个字符
.+
再次匹配任何内容。 +表示“一次或多次”,因此将匹配超出我们上面匹配的15个字符的字符,...
$
......直到行尾
现在替换位:
\1
替换为\ 1
的内容...
和三个点。
完成!
答案 2 :(得分:1)
使用Perl正则表达式:
$ echo 'this is a long string that needs to be shortened' \
| perl -pe 's/^(.{15}).+/$1.../'
this is a long ...
考虑正则表达式的最简单方法是将其视为需要匹配的模式。在这种情况下,模式从行的开头开始:
^
(请注意,/
是一个任意分隔符。可以使用其他字符。)^
是表示正则表达式中行的开头的符号。接下来正则表达式匹配任何字符:
^.
.
是任何字符的正则表达式符号。但我们希望匹配前15个字符:
^.{15}
有几种不同的修饰符代表重复。最常见的是*
,表示0或更多。 +
表示1或更多。 {15}
显然恰好代表15.({...}
符号更为通用。因此*
可以写为{0,}
而+
与{1,}
相同现在我们需要捕获前15个字符,以便我们以后可以使用它们:
^(.{15})
捕获(
和)
之间的所有内容,并将其放置在名为$1
(或有时为\1
)的特殊变量中。捕获的第二个块将放在$2
中,依此类推。最后,你需要匹配到行的末尾,以便你可以扔掉那部分:
^(.{15}).+
我最初使用*
,但正如另一个人所指出的那样,当字符串长度恰好为15个字符时,可能不是所需的:
$ echo 'this is a long ' \
| perl -pe 's/^(.{15}).*/$1.../'
this is a long ...
使用+
表示如果没有要替换的16 th 字符,模式将不匹配。
声明的后半部分是印刷品:
$1...
使用我们之前捕获的$1
变量,并且替换的这一侧的点是文字.
。通常,除了正则表达式变量之外的所有内容都是替换语句右侧的文字。
答案 3 :(得分:0)
在perl中,你可以写s/(.{15}).*/$1.../
。我不确定sed可以使用{15}表示法,但如果没有,s/\(...............\).*/\1.../
(组中有15个点)。
我永远不记得在sed中分组时是否需要转义(
。我刚刚尝试过,您需要\(
和\)
答案 4 :(得分:0)
你是否真的只想在第15个角色之后重击一切,或者你是否想要施加15个字符的最大长度?如果字符串长度为16个字符怎么办?到目前为止提出的所有解决方案都将切掉一个多余的字符,只用三个点替换它。 (我知道Konrad和Paul使用省略号字符,但OP在示例中使用了三个点;我们应该对此做出裁决。)
如果你想将字符串修剪为最大长度15 ,包括三个点,你可以这样做:
s/^\(.\{12\}\).\{3\}.\+$/\1.../
如果超过15个字符,它仍然只匹配,但是它会在第12个字符之后切掉所有内容,为点提供空间。