我有一个源文本文件,其中包含一些文本,其中一些单词是字母间隔的,就像这个问题中的单词“letterspaced”(即,单词的字母之间有一个空格字符。
如何使用 sed 取消字母间距?
像这样的模式\{[A-Za-z] \}+[A-Za-z]
捕获字母间隔的单词,并s/ //g
取出空格,但是如何从一行文本中提取字母间隔的单词并撤消字母间隔,而不损害文本其余部分中的合法空格字符?
答案1
你可以这样做:
sed -e's/ \([^ ][^ ]\)/\n\1/g' \
-e's/\([^ ][^ ]\) /\1\n/g' \
-e's/ //g;y/\n/ /
' <<\IN
I have a source text file containing text where
some words are l e t t e r s p a c e d
like the word "letterspaced" in this question
(i.e., there is a space character between the
letters of the word.
IN
这个想法是首先找到前面或后面有两个或多个非空格字符的所有空格,并将它们作为换行符放在一边。接下来只需删除所有剩余的空格即可。最后,将所有换行符翻译回空格。
这并不完美——如果没有包含每个单词的完整字典,你可能会使用的最好的方法是某种启发式方法。不过这个还是蛮不错的
另外,根据sed
您使用的,您可能必须使用文字换行符来代替n
我也在前两个替换语句中使用。
不过,除了这个警告之外,这对于任何 POSIX 都可以工作,而且工作得非常快sed
。它不需要执行任何昂贵的前向或后向操作,因为它只是节省了不可能的情况,这意味着它可以处理单个地址中每个替换的所有模式空间。
输出
I have a source text file containing text where some
words are letterspaced
like the word "letterspaced" in this question
(i.e., there is a space character between the
letters of the word.
答案2
最有效的 Perl 方法:
perl -C -lpe 's/(?:^|\P{L})\K\p{L}(?:\s\p{L})+(?=\P{L}|$)/$&=~s{\s}{}rgo/goe'
这假设 Perl 的版本足够新,可以了解/r
替换中的标志。
概念证明:
$ echo 'Do I like «ł é t t ê r s p ä c è đ» text?' | perl -C -lpe 's/(?:^|\P{L})\K\p{L}(?:\s\p{L})+(?=\P{L}|$)/$&=~s{\s}{}rgo/goe'
Do I like «łéttêrspäcèđ» text?
答案3
Perl 的前瞻断言使这一切变得简单。 AFAIK,sed 缺少这些。
鉴于两个或多个空格分隔单词,这消除了单个空格,但留下两个或多个未改变的序列:
perl -pe 's/\s(?!\s)//g' myfile
该p
开关使 Perl 读取myfile
并替换后面\s
不跟有另一个空格的单个空格 ( )。这是 给出的否定前瞻断言(?!\s)
。