【问题标题】:Non greedy and a fixed number of characters search and replace in VIMVIM 中的非贪婪和固定数量的字符搜索和替换
【发布时间】:2016-08-28 05:15:22
【问题描述】:

我有很多这样的字符串 -

icon=null restored=0 title=Adblock Browser itemType=0 container=-101

我想替换 = 之后的每个字符串,以便有一个 | 分隔两个字段。

在上面的示例中,我希望将字符串替换为 -

icon=null |restored=0 |title=Adblock Browser |itemType=0 |container=-101

在 VIM 中,我尝试了以下 search-and-replace 表达式 -

:%s/=.\{-} \?.\{-} /\0|/gc

但是,这里的问题是,它不匹配 =Adblock Browser,它只匹配 =Adblock 部分。


关于我使用.\{-} 的部分是因为有时字符串是这样的 -

icon=null profileId=0 screen=0 modified=1462258474716 iconPackage=null iconResource=null spanX=1 cellX=2 displayMode=null appWidgetProvider=null intent=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.google.android.play.games/com.google.android.gms.games.ui.destination.main.MainActivity;end restored=0 title=Play Games itemType=0 container=8 iconType=null isShortcut=null spanY=1 _id=14 cellY=1 uri=null appWidgetId=-1
icon=null profileId=0 screen=1 modified=0 iconPackage=null iconResource=null spanX=1 cellX=3 displayMode=null appWidgetProvider=null intent=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.vending/.AssetBrowserActivity;end restored=0 title=Play Store itemType=0 container=-100 iconType=null isShortcut=null spanY=1 _id=15 cellY=3 uri=null appWidgetId=-1
icon=null profileId=0 screen=4 modified=0 iconPackage=null iconResource=null spanX=1 cellX=4 displayMode=null appWidgetProvider=null intent=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;package=org.adblockplus.browser;component=org.adblockplus.browser/.App;end restored=0 title=Adblock Browser itemType=0 container=-101 iconType=null isShortcut=null spanY=1 _id=19 cellY=0 uri=null appWidgetId=-1

输出应该是这样的 -

icon=null |profileId=0 |screen=0 |modified=1462258474716 |iconPackage=null |iconResource=null |spanX=1 |cellX=2 |displayMode=null |appWidgetProvider=null |intent=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.google.android.play.games/com.google.android.gms.games.ui.destination.main.MainActivity;end |restored=0 |title=Play Games |itemType=0 container=8 |iconType=null |isShortcut=null |spanY=1 |_id=14 |cellY=1 |uri=null |appWidgetId=-1

其他字符串也类似。


最小的、可验证的例子

这是输入文件的内容-

icon=null profileId=0 screen=4 modified=0 iconPackage=null iconResource=null spanX=1 cellX=4 displayMode=null appWidgetProvider=null intent=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;package=org.adblockplus.browser;component=org.adblockplus.browser/.App;end restored=0 title=Adblock Browser itemType=0 container=-101 iconType=null isShortcut=null spanY=1 _id=19 cellY=0 uri=null appWidgetId=-1

VIM 中的搜索和替换表达式 -

:%s/=.\{-} \?.\{-} /\0|/gc

输出:

icon=null |profileId=0 |screen=4 |modified=0 |iconPackage=null |iconResource=null |spanX=1 |cellX=4 |displayMode=null |appWidgetProvider=null |intent=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;package=org.adblockplus.browser;component=org.adblockplus.browser/.App;end |restored=0 |title=Adblock |Browser itemType=0 |container=-101 |iconType=null |isShortcut=null |spanY=1 |_id=19 |cellY=0 |uri=null |appWidgetId=-1

错误部分 -

restored=0 |title=Adblock |Browser itemType=0 |container=-101 |

应该是——

restored=0 |title=Adblock Browser |itemType=0 |container=-101 |

【问题讨论】:

  • sed 's/[a-zA-Z]*=/|&/g' file 解决了这个问题,只是它在一开始添加了一个|
  • @fedorqui 正如我在问题的第二部分中提到的那样,字符串不是很简单。例如intent=#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.google.android.play.games/com.google.android.gms.games.ui.destination.main.MainActivity;end 除了普通的 [a-zA-Z] 字符之外还有很多其他字符,添加 ; 或 ` ` 会使整个事情变得混乱。
  • 好的,我明白了。如果您可以edit 并显示涵盖所有这些情况的minimal reproducible example 以及预期的输出,那就太好了。
  • @fedorqui 问题有导致错误的给定输入以及错误部分。无论如何,我已经用一个 Minimal Verifiable example 更新了这个问题。
  • 这个怎么样::%s/\s\zs\ze\S\+=/|/g

标签: regex vim sed


【解决方案1】:
sed -r 's/ ([^= ]*=)/ |\1/g' file

这将匹配一个空格,后跟 0 个或多个字符,除了空格或 =,然后是 =。 () 括号内的字符串捕获将在\1 中,即第一个capturing group\0 将在组内捕获所有字符串。
然后将匹配替换为| \1

【讨论】:

  • 这行得通。你能解释一下正则表达式吗?还有\0\1等有什么区别
  • 所以您匹配的是 title= 而不是 =Adblock Browser 。这很聪明。
【解决方案2】:

我有一些坏消息要告诉你:在 sed 中,量子是贪婪的。你也没有环视,所以你不能在 sed 中做到这一点。

好消息:perl 可以帮助您。这是一个用 perl 实现几乎所有东西的脚本:

echo "icon=null restored=0 title=Adblock Browser itemType=0 container=-101" |
perl -p -e 's/([^ =]*=)/|\1/g'

不幸的是,它会有一个领先的管道。但这很容易解决 - 但有点脏,我知道:

echo "icon=null restored=0 title=Adblock Browser itemType=0 container=-101" |
perl -p -e 's/([^ =]*=)/|\1/g' | 
sed 's/^|//g'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2021-07-02
    • 2011-05-15
    相关资源
    最近更新 更多