我应该使用什么命令行工具来使用复杂的正则表达式从文件中提取字符串

时间:2017-01-18 16:25:44

标签: regex

问题

在linux脚本中,我想用文件中的数据分配几个变量。

该命令应该能够:

  • 使用复杂的regexp:意思是普通的java / javascript / php / perl regexps, 我可以适应一些变化
  • 在stdout返回第一个捕获组(或参数指定的捕获组)。如果它支持命名捕获组,则可以接收名称作为参数:`regextractor“”
  • 理想情况下应该已经存在于标准的Linux发行版中,也可能存在于osx上

样品

我正在搜索像

这样的命令
mydate=`regextractor "^date:\s*(\S{10}).*$" myfile.md`
mytitle=`regextractor "^title:\s*(.*)\s*$" myfile.md`
echo $mydate - $mytitle

我的档案:

---
slug: article1
date: 2012-01-29 15:34:01
title: What is the best monetary system invented til now?
author: raisercostin<raisercostin@gmail.com>
tags: currency,monetary,system
type: question
toslug: article

此处测试了正则表达式:https://regex101.com/r/y311eP/1

我试过

  • 更新:grep - 默认grep使用简化的正则表达式  grep -o "toslug:\(.*\)" myfile.md =&gt; toslug: article
  • 更新:grep扩展 - 它支持复杂的正则表达式,但不支持捕获组   grep --color=no -oE "toslug:(.*)" myfile.md =&gt; toslug: article
  • sed - 它不支持捕获组,因此返回一行。  sed -nE "s/^date:\s*(\S*)//p" myfile.md  更新:它实际上支持捕获组,但您需要启用--regexp-extended with -E parameter
  • awk - 它不支持捕获组,因此返回一行  awk '/^date:\s*(.*)$/' myfile.md

更新

  • 在我的Linux vagrant-ubuntu-trusty-64 3.13.0-101-generic #148-Ubuntu SMP Thu Oct 20 22:08:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux上:
    • sed没有记录-E选项,但适用于某些情况
    • 工作 sed -nE 's/^date:\s*(\S*)/\1/p' myfile.md =&gt; 2012-01-29 15:34:01
    • 无法工作 sed -nE 's/^date:\s*(\S{10})/\1/p' myfile.md =&gt; 2012-01-29 15:34:01
    • 无法工作 sed -nE 's/^date:\s*(\S*)$/\1/p' myfile.md =&gt;没有线
    • 工作 awk '{ match($0, /^date:\s*(\S{10}).*$/, a); if(a[1])print a[1]}' myfile.md =&gt; 2012-01-29
  • 在我的Darwin costins-MBP.router1 16.3.0 Darwin Kernel Version 16.3.0: Thu Nov 17 20:23:58 PST 2016; root:xnu-3789.31.2~1/RELEASE_X86_64 x86_64上:
    • 部分工作 sed -nE 's/^date:\s*(\S*)/\1/p' myfile.md =&gt; 2012-01-29 15:34:01 - 不消耗初始空格
    • 无法工作 sed -nE 's/^date:\s*(\S{10})/\1/p' myfile.md =&gt;没有线
    • 无法工作 sed -nE 's/^date:\s*(\S*)$/\1/p' myfile.md =&gt;没有线
    • 无法工作 awk '{ match($0, /^date:\s*(\S{10}).*$/, a); if(a[1])print a[1]}' myfile.md =&gt; awk: syntax error at source line 1{ match($0, >>> /^date:\s*(\S{10}).*$/, <<<

3 个答案:

答案 0 :(得分:1)

这是一个perl oneliner:

    protected virtual void Dispose(bool disposing)
    {
        // Note: Never change this to call other virtual methods on Stream
        // like Write, since the state on subclasses has already been 
        // torn down.  This is the last code to run on cleanup for a stream.
    }

<强>输出:

perl -E 'undef$/;$_=<>;($d,$t)= $_ =~  /\ndate:\s*(\S{10}).+\ntitle:\s*(.+?)\R/s;say "$d - $t";' <file.txt 

file.txt的

2012-01-29 - What is the best monetary system invented til now?

答案 1 :(得分:1)

(gnu)awk支持捕获:

awk '/^date/ { match($0, /^date:[[:blank:]]*([^[:blank:]]{10}).*$/, a); print a[1]}' myfile.md

给出:2012-01-29

awk '/title/ { match($0, /^title:[[:blank:]]*([^[:blank:]]*.*$)/, a); print a[1]}' myfile.md

给出:What is the best monetary system invented til now?

答案 2 :(得分:0)

基于Jan Smydke的回应。这匹配两组。

<强>输入:

regextractor () {
    perl -E 'undef$/;$_=<>;($v1,$v2)= $_ =~ /'$1'/m;say "$v1$v2";' <$2
}
regextractor "^date:\s*(\S{10}).*$" myfile.md
regextractor "^title:\s*(.*)\s*$" myfile.md

<强>输出:

2012-01-29
What is the best monetary system invented til now?