【问题标题】:Removing specific character from anywhere between two specific strings?从两个特定字符串之间的任何位置删除特定字符?
【发布时间】:2014-09-01 13:52:58
【问题描述】:

我有一个包含以下示例内容的大文本文件:

number="+123 123 123" text="This is some text"
number="+123456" text="This may contain numbers"
number="+123456 789" text="Numbers here should keep their spaces"
number="+9 8 7 6 5" text="example 123 123 123"

我想要删除两个标识字符串之间的任何空白字符,在本例中为number=" text=,而不触及该行的其余部分。这样所需的输出将是:

number="+123123123" text="This is some text"
number="+123456" text="This may contain numbers"
number="+123456789" text="Numbers here should keep their spaces"
number="+98765" text="example 123 123 123"

(?<=[0-9])(\s)(?=[0-9]) 之类的正则表达式会干扰文本字段,这是不可取的。

我已经测试了一些使用类似(?<=address)(\s)(?=date) 的变体,但这不起作用。我认为问题在于无法处理空格和标记之间可能存在的额外数字?

将通配符匹配添加到诸如(?<=address.*)(\s)(?=.*date) 之类的lookbehinds/lookaheads 中似乎无效,或者我做错了?同样使用(/s+?) 让空格变得懒惰似乎对我没有帮助,但这是关于我对正则表达式的了解真正崩溃的地方:)

理想情况下,为了安全起见,我还想限制额外的等号和引号字符。即 number=" 在开始标记和 text=" 作为结束标记。

如果更简单,也欢迎任何 sed/awk 或类似解决方案。

【问题讨论】:

  • 除了number="+ 之后的那个以外,行中的其他地方是否可以有应该缩短的数字?示例number="+123 123 123" text="This is some text" number2="+435 234 132

标签: regex parsing sed


【解决方案1】:

使用替换和循环:

sed ':l s/\(number="[^" \t]*\)\s\s*/\1/g;tl' input

这个给出:

number="+123123123" text="This is some text"
number="+123456" text="This may contain numbers"
number="+123456789" text="Numbers here should keep their spaces"
number="+98765" text="example 123 123 123"

【讨论】:

  • +1;不过,g 不是必需的。假设 GNU sed。对于 POSIX 合规性,请使用 sed -e ':l' -e 's/\(number="[^" \t]*\) \{1,\}/\1/;tl' input
【解决方案2】:

搜索: [ ](?=[^"]*" text=)(空格周围的[brackets] 是可选的,它们是为了清晰起见)

替换:空字符串。

the regex demo 中,请参阅底部的替换。

命令行语法

我不知道要搜索和替换的 sed 语法。使用 Perl(@jaypal 和 @AvinashRaj 提供):

perl -pe 's/ (?=[^"]*" text=)//g' file

来自perl --help

-p                assume loop like -n but print line also, like sed
-e program        one line of program (several -e's allowed, omit programfile)

【讨论】:

  • 不,通过 sed 是不可能的。
  • @AvinashRaj 我不知道 sed。你能解释一下哪一部分是不可能的吗?
  • 在 sed | 中被视为分隔符而不是逻辑运算符。
  • @zx81 前瞻是不可能的,但你当然可以使用perl 并且没有Avinash | 不仅仅是一个分隔符。它也是一个逻辑运算符。
  • @zx81 这是一个perl,使用您的regex 以保证完整性;)perl -pe 's/(text="[^"]*")| (?=[^"]*" text=)/$1/g' file。很狡猾regex+1
【解决方案3】:

使用awk

awk 'BEGIN{FS=OFS="\""}{gsub(/ /,"",$2)}1' file
number="+123123123" text="This is some text"
number="+123456" text="This may contain numbers"
number="+123456789" text="Numbers here should keep their spaces"
number="+98765" text="example 123 123 123"

【讨论】:

  • 我确实喜欢awk 之前的sed 解决方案,因为它更具可读性。打高尔夫球让它更短一点:awk -F\" '{gsub(/ /,"",$2)}1' OFS=\" file
【解决方案4】:

另一个awk解决方案:

 awk -F ' text="' '{ gsub(/ /, "", $1); print $1 FS $2 }' file
  • -F text="' 将每个输入行拆分为 text=" ($1) 之前的部分和 ($2) 之后的部分 - -F 选项设置特殊的 FS (*f*ield *s*eparator ) awk 变量为一个正则表达式,awk 用于将每个输入行拆分为字段。
  • gsub(/ /, "", $1) (*g*lobal *sub*stitution) 删除 $1 中的所有空格(text=" 之前的部分;用空字符串替换空格)。
  • print $1 FS $2 打印输出:已修改 $1(删除空格),与FS(即text=")连接,与$2text=" 之后的未修改部分)连接)。

【讨论】:

    【解决方案5】:

    注意:这是对现有答案的补充,以比较他们的表现

    测试环境

    • OS X 10.9.4。
      • FreeBSD awk 20070501
      • FreeBSD sed(不知道版本号)
      • Perl v5.16.2
    • Ubuntu 14.04
      • GNU awk 4.0.1
      • sed (GNU sed) 4.2.2
      • Perl v5.18.2

    不足之处

    在 OS X 上,差异并不显着。
    在 Ubuntu 上,awkperl 解决方案之间的差异很小,但 sed 解决方案的速度要慢得多。

    样本数字,针对 100,000 行的输入文件运行 10 次。 不要直接比较它们(Ubuntu 在 OS X 机器上的虚拟机中运行),只看它们的比率。 (奇怪的是,awkperl 在 Ubuntu 虚拟机中运行更快):

    操作系统:

    # awk (@japyal) 实际0m3.848s 用户 0m3.773s 系统 0m0.049s # awk (@mklement0) 真正的 0m4.011s 用户 0m3.959s 系统 0m0.045s # perl 真实0m4.382s 用户 0m4.291s 系统 0m0.063s # sed 真正的 0m4.867s 用户 0m4.816s 系统 0m0.044s # sed(没有`g`) 真正的 0m4.510s 用户 0m4.460s 系统 0m0.044s

    Ubuntu:

    # awk (@mklement0) 真正的 0m1.850s 用户 0m1.788s 系统 0m0.020s # awk (@jaypal) 实际0m2.055s 用户 0m1.996s 系统 0m0.012s # perl 实际0m2.349s 用户 0m2.276s 系统 0m0.024s # sed 真实0m8.278s 用户 0m8.196s 系统 0m0.016s # sed(没有`g`) 真正的 0m7.580s 用户 0m7.488s 系统 0m0.028s

    【讨论】:

    • @jaypal:我的荣幸;我有一种预感,sed 解决方案会因为循环而变慢。我发现平台差异很有趣。
    • sed 和 perl 解决方案由于使用正则表达式、大量回溯 (perl) 和循环 (sed) 而变慢。我对 awk 的区别更好奇,尽管它相当接近。
    • @jaypal:好点;刚刚在 Ubuntu 上使用 mawk 运行,您的解决方案再次是更快的解决方案(不是很多),并且与 gawk 相比,两者都在不到 三分之一 的时间内完成 - 有趣的是快了多少mawk 是。使用这些awk 解决方案,我的VM 中的mawk 在主机上的运行速度大约是FreeBSD awk 的7 倍......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多