从两个特定字符串之间的任何位置删除特定字

时间:2014-07-11 02:33:08

标签: regex parsing sed

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

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)行的一些变体,但这不起作用。我认为问题在于无法处理空格和标记之间的额外可能数字?

将通配符匹配添加到lookbehinds / lookaheads(例如(?<=address.*)(\s)(?=.*date))似乎无效,否则我做错了?使用(/s+?)使空白变得懒惰似乎对我没有帮助,但这是关于我对正则表达式的知识真正崩溃的地方:)

理想情况下,我还想在额外的等于和引号字符之间限制安全性。 I.e number="位于开头标记处,text="作为结束标记。

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

5 个答案:

答案 0 :(得分:4)

使用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"

答案 1 :(得分:3)

使用替换和循环:

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"

答案 2 :(得分: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)

答案 3 :(得分:1)

另一个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="之后的未经修改的部分)。

答案 4 :(得分:1)

注意:这是对现有答案的补充比较其效果

测试环境

  • 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机器上的VM中运行),只需看看它们的比率。 (奇怪的是,awkperl在Ubuntu VM中运行更快

OS X:

# awk (@japyal)
real    0m3.848s
user    0m3.773s
sys 0m0.049s

# awk (@mklement0)
real    0m4.011s
user    0m3.959s
sys 0m0.045s

# perl
real    0m4.382s
user    0m4.291s
sys 0m0.063s

# sed
real    0m4.867s
user    0m4.816s
sys 0m0.044s

# sed  (no `g`)
real    0m4.510s
user    0m4.460s
sys 0m0.044s

Ubuntu的:

# awk (@mklement0)
real    0m1.850s
user    0m1.788s
sys 0m0.020s

# awk (@jaypal)
real    0m2.055s
user    0m1.996s
sys 0m0.012s

# perl
real    0m2.349s
user    0m2.276s
sys 0m0.024s

# sed
real    0m8.278s
user    0m8.196s
sys 0m0.016s

# sed (no `g`)
real    0m7.580s
user    0m7.488s
sys 0m0.028s