【问题标题】:Getting Exact Pattern Match with grep and sed使用 grep 和 sed 获得精确的模式匹配
【发布时间】:2019-11-09 06:32:04
【问题描述】:

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

例如:

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

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

P.S:我学习 grepsed 只是为了好玩。

【问题讨论】:

  • 查看 grep 的 -o 标志

标签: string bash shell sed grep


【解决方案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 只打印匹配的子字符串。
  • 模式(?&lt;=package:)positive lookbehind assertiongrep -o 的输出中不包含匹配的子字符串。
  • 模式(?=/[^/]*$) 也是positive lookahead assertion

sed 替代方案将是:

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

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

后者会更清晰。

您会看到 positive lookarounds 可以替换为 sed 的反向引用,只需丢弃不必要的组。

希望这会有所帮助。

【讨论】:

  • 谢谢@tshiono,虽然模式对我来说非常复杂,但它工作得很好。你也可以用SED 来做吗?顺便说一句,学习GREPSED 的最佳资源是什么。我查看了Youtube,但没有找到关于它们的完整课程。
  • @Mujtaba 很高兴知道它有效。我通过添加sed 替代方法更新了我的答案。 (我想@potong的-n选项解决方案会更聪明。我只是直接将我的grep版本翻译成sed。)
  • 关于正则表达式,虽然grepsed 都支持正则表达式,但它们是用于不同目的的不同工具。我建议从 sedawk 开始。那么如果你接下来需要强大的正则表达式,请尝试perlrubypython。祝你好运。
【解决方案2】:

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

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

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

注意使用替换命令,程序员可以选择它的分隔符。在文档中,命令通常写为s/LHS/RHS/flags,其中分隔符为/,但可以是任何字符,如上述解决方案中选择# 以减少引用/ 字符的需要,LHS = regexp左侧,RHS = 替换和标志 = 附加操作,例如 g 表示在整个行/文件中全局替换,p 表示在成功替换后以当前状态打印行(还有其他操作请参阅 sed 文档。

【讨论】:

  • 感谢 @potong 的精彩解释。
猜你喜欢
  • 2015-10-03
  • 2013-11-28
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 2018-01-23
  • 1970-01-01
相关资源
最近更新 更多