使用grep和sed进行精确模式匹配

时间:2019-11-09 06:32:04

标签: string bash shell sed grep

我正在使用grepsed解决一堆文本字符串,其中我只希望 stdout 之后打印数据package: ,并以文件夹名称结尾,结尾没有 /

例如:

data/dataapp/com.android.chrome-DeX_54==
System/app/Keychain
vendor/app/NlpService

这是示例...

package:data/app/com.android.chrome-DeX_54==/base.apk=com.android.chrome
package:data/dataapp/ExactCalculator/ExactCalculator.apk=com.android.calculator2
package:data/hw_init/cust/app/Email/Email.apk=com.android.email
package:system/app/KeyChain/KeyChain.apk=com.android.keychain
package:system/delapp/WallpaperBackup/WallpaperBackup.apk=com.android.wallpaperbackup
package:system/framework/framework-res.apk=android
package:system/priv-app/CIT/CIT.apk=com.ontim.cit
package:vendor/app/NlpService/NlpService.apk=com.mediatek.nlpservice

我没有得到想要的确切输出,因此将不胜感激。

PS:我正在学习grepsed只是为了好玩。

2 个答案:

答案 0 :(得分:1)

请您尝试:

grep -Po '(?<=package:).+(?=/[^/]*$)' input.txt

结果:

data/app/com.android.chrome-DeX_54==
data/dataapp/ExactCalculator
data/hw_init/cust/app/Email
system/app/KeyChain
system/delapp/WallpaperBackup
system/framework
system/priv-app/CIT
vendor/app/NlpService
  • -P选项启用与Perl兼容的正则表达式。
  • -o选项告诉grep仅打印匹配的子字符串。
  • 模式(?<=package:)positive lookbehind assertion,并且 匹配的子字符串不包含在grep -o的输出中。
  • 模式(?=/[^/]*$)也是positive lookahead assertion

sed的替代方案将是:

sed 's#\(^package:\)\(.\+\)\(/[^/]*$\)#\2#' input.txt

sed -E 's#(^package:)(.+)(/[^/]*$)#\2#' input.txt

后者会更清晰。

您将看到positive lookarounds可以用sed的后向引用代替,只需丢弃不必要的组即可。

希望这会有所帮助。

答案 1 :(得分:1)

这可能对您有用(GNU sed):

sed -n 's#^package:\(.*\)/.*#\1#p' file

由于这可能是过滤操作,请使用-n选项显式打印结果。 regexp从替换命令中的^开始,该命令将package:锚定到行的开头,并使用.*贪婪地消耗行的其余部分。但是,它尝试匹配的下一个字符是/,因此正则表达式引擎回溯以找到它,然后后面的.*再次吞噬了该行的其余部分。用引号括起来的括号\(...\)捕获了正则表达式的这一部分,并用\1表示在替代命令的RHS中,称为反向引用。替换命令末尾的p标志显式地显示修改后的行的当前状态。

使用替代命令,程序员可以选择其定界符。在文档中,命令通常写为s/LHS/RHS/flags,其中定界符为/,但可以是上述解决方案#中选择的任何字符,以减少对{{1}的引用。 }字符,左侧为LHS = regexp,右侧为RHS =替换,标志=其他操作,例如/表示在行/文件中全局替换,g表示在当前状态下打印行成功的替代品(还有其他参考sed文档。