正则表达式:用相同数量的其他字符替换任意数量的空格

正则表达式:用相同数量的其他字符替换任意数量的空格

我想要做的是获取一个格式类似于目录的列表并用点替换左右文本之间的空格(单个空格字符,而不是制表符),只保留最外面的两个空格字符。

具体来说,我想要列出如下清单:

foo        url1
foobar     url2
foo bar    url3

并将其转换为:

foo ...... url1
foobar ... url2
foo bar .. url3

我正在使用Eclipse 集成开发环境用于编辑我的文本。我不熟悉不同的正则表达式引擎,但我猜它使用 Jakarta Regexp 或 java.util.regex(我在 Wikipedia 上查过)。

我可以捕获寻找字段中使用“ ( +)”,但我不知道如何将它们转换为相同数量的点在用。。。来代替场地。

我谷歌了一下,发现了这个问题(我就是在这里学会了“ ( +)”语法的)。听起来这可能是和我的问题相同或类似的问题。但我要么没有找到答案,要么就是不理解给出的答案。

答案1

问题明确指出标题将包含空格。为了安全起见,我假设标题可能包含点(句号);例如,“3.14159 的历史”或“杜立特医生的发现”。我的答案假设有一些永远不会出现在目录中的字符;具体来说,它们假设它是@。如果你@的表中有 ,请用一些永远不会出现的字符替换它(例如 、#^_|)。如果你真的使用每个 ASCII 字符,你可能需要使用字符序列,如<@>

有三种方法可以实现sed

环形:

sed 's/\(.*\)\( \)/\1@\2/; :loop; s/  @/ @./; t loop; s/@//'
  • s/\(.*\)\( \)/\1@\2/找到行中的最后一个空格并@在其前插入一个。
  • :loop是一个标签,就像一个里程标记。
  • s/ @/ @./(即s/␣␣@/␣@./,为了避免歧义)表示,如果 之前有两个空格@,则将其替换为␣.(空格和点),并将 移到@它们之间。
  • t loop表示,如果上述替换成功,则跳回标记:loop并重复。否则,继续
  • s/@//,这将删除@

因此,foo bar表中的行将按如下方式处理:

初始值:foo bar url3
s/\(.*\)\( \)/\1@\2/ foo bar @ url3
s/@/@./foo bar@.url3
s/@/@./foo bar@..url3
s/@/@./foo bar@..url3        (替换失败,因此不要循环)
s/@// foo 栏.. url3
最终输出:foo bar..url3

压倒性的数字:

sed 's/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/; s/ [ @]\{20\}/ /; s/@/./g'
  • s/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/ 与第一个解决方案中的第一个子命令非常相似s;它找到行上的最后一个空格并 @在其前面插入一个 20 个字符的字符串。这实际上应该是一个数字,至少与您需要在一行上插入的最大点数一样大;例如,80。管理 80 个 @字符的字符串会很尴尬;您可能希望将其替换为
    • s/\(.*\)\( \)/\1<@><@><@><@><@>\2/; s/<@>/@@@@@@@@/g 插入一个由 5 个<@>序列组成的字符串,然后将每个序列替换为一个由 16 个 @字符组成的字符串,最终得到 5×16=80 个 @字符。
  • s/ [ @]\{20\}/ /查找一个由 20 个连续字符组成的字符串,这些字符要么是空格,要么是@,前面有一个空格,然后将其替换为前面的空格。20用上一步中的数字替换。
  • s/@/./g@用点替换剩余的每个点。

因此,foo表中的行将按如下方式处理:

Initial value:                  foo        url1
s/\(.*\)\( \)/\1@@@@...@@@@\2/  foo       @@@@@@@@@@@@@@@@@@@@ url1
s/ [ @]\{20\}/ /                   _[↑↑↑↑↑↑remove↑↑↑↑↑↑]
                                foo @@@@@@ url1
s/@/./g                         foo ...... url1

使用“保留空间”:

sed 's/.*[^ ] /&@/; h; s/ /./g; s/\(\.*\)\./\1 /; x; G; s/@.*@//'
  • s/.*[^ ] /&@/相似的到前面的命令;它找到标题的结尾 — — 准确地说,是非空白字符后跟空格的最后一个位置 — — 并在@其后插入一个。
  • h将该行复制到保留空间。
  • s/ /./g用点替换行中的所有空格。
  • s/\(\.*\)\./\1 /将最后一个点替换为空格。(如果 URL 可以包含点,则需要更改此设置,我猜这是有可能的。)
  • x交换模式空间和保持空间。
  • G将保留空间附加到模式空间。现在,我们基本上有了该行的两个副本。
  • s/@.*@//保留第一份副本的第一部分和第二份副本的第二部分,删除中间的内容。
Initial value: foo bar    url3

                      Pattern space                            Hold space
s/.*[^ ] /&@/       foo bar @   url3
h                   foo bar @   url3                        foo bar @   url3
s/ /./g             [email protected]                        foo bar @   url3
s/\(\.*\)\./\1 /    foo.bar.@.. url3                        foo bar @   url3
x                   foo bar @   url3                        foo.bar.@.. url3
G                   foo bar @   url3 foo.bar.@.. url3       foo.bar.@.. url3
s/@.*@//            foo bar .. url3                         foo.bar.@.. url3

Final output:   foo bar .. url3

答案2

你可以用 Notepad++ 来做

  • Ctrl+H
  • 找什么:(?<!\S) (?= )
  • 用。。。来代替:.
  • 检查环绕
  • 检查正则表达式
  • Replace all

解释:

(?<!    : Start negative lookbehind, make sure we have not
  \S    : a non-space character
)       : end lookbehind
        : a space
(?=     : start lookahead, make sure we have
        : a space
)       : en lookahead

替代品:

.       : a dot

给定示例的结果:

foo ...... url1
foobar ... url2
foo bar .. url3

相关内容