非贪婪和固定数量的字符在VIM中搜索和替换



我有很多字符串,它们类似于

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/=.{-} ?.{-} /|/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/=.{-} ?.{-} /|/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 -r 's/ ([^= ]*=)/ |1/g' file

这将匹配后面跟着0个或多个字符的空白,但空白或后面跟着==除外。()括号内的字符串捕获将在1中,即第一个捕获组中。将在组内捕获所有字符串
然后用| 1 替换匹配

我有个坏消息要告诉你:在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'

最新更新