Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python grep,awk,bash和朋友们?有什么工具可以读取这些数据吗?_Python_Perl_Bash_Awk - Fatal编程技术网

Python grep,awk,bash和朋友们?有什么工具可以读取这些数据吗?

Python grep,awk,bash和朋友们?有什么工具可以读取这些数据吗?,python,perl,bash,awk,Python,Perl,Bash,Awk,我正在搜索输入,以提取每个记录的特定信息。可悲的是,每一张唱片都分散在多行上,例如(简化摘录) 我唯一真正关心的是标识符和年龄(示例中为01238584和81)。非常清楚的是,我可以在输入中可靠地搜索到的唯一接近这两行的正则表达式是 \[age=[0-9]+\] 。。。当然,我想打印出年龄以及上面一行的识别记录号,例如 01238584 81 凭借我所有的系统管理员shell经验和对awk的熟练掌握,我还没有想出一个解决方案。当然,我可以使用grep-B1来获取每一行,但是接下来呢?我

我正在搜索输入,以提取每个记录的特定信息。可悲的是,每一张唱片都分散在多行上,例如(简化摘录)

我唯一真正关心的是标识符和年龄(示例中为01238584和81)。非常清楚的是,我可以在输入中可靠地搜索到的唯一接近这两行的正则表达式是

\[age=[0-9]+\]
。。。当然,我想打印出年龄以及上面一行的识别记录号,例如

 01238584   81
凭借我所有的系统管理员shell经验和对awk的熟练掌握,我还没有想出一个解决方案。当然,我可以使用
grep-B1
来获取每一行,但是接下来呢?我总是用awk来做这类事情。。。但是关联的数据总是在同一行中。唉,这绝对超出了我目前的awk技能

谢谢你的阅读。有什么建议吗


编辑
我同意查理的建议,并改变awk的记录分隔符,这是我以前从未做过的。它不漂亮,但输入也不漂亮。工作完成了

egrep -B1 '\[age=[0-9]+\]' inputfile |
awk '
  BEGIN{ RS = "--" }
  { printf "%s  %s\n", $1, gensub(/.*\[age=([0-9]+)\].*/, "\\1", 1) }'

你能显示更多的输入文件吗?例如,如果数据记录由空行分隔,则可以使用Awk中的RS特殊变量更改记录分隔符,使其将多行视为一条记录。(参见,例如)

在任何情况下,我都会尝试将所有数据记录放在一行或一个逻辑记录中

如果您不能做到这一点,但您知道记录ID始终位于age标记之前的行上,那么在Python中使用readlines很容易做到这一点,它将整个文件读入一个行列表,类似这样

 with open("file.dat") as f:
     lines = f.readlines()
     for ix, line in enumerate(lines):
         if # line has age field
            # get record from lines[ix-1]
当然,您也可以将前一行保留在Awk的内存中

 BEGIN { prevline = "" }
       { # process the line
         prevline = $0
       }

在这种情况下,Perl很容易成为您的朋友。你可以看报纸 将整个文件放入内存中,以便在多行上应用正则表达式。将输入记录分隔符设置为
0777
会导致此类“slurping”操作。
-n
开关只表示读取命令行上提供的一个或多个文件。
-e
开关的参数构成要执行的代码

正则表达式的
/s
修饰符允许
匹配换行符。
\m
修饰符允许
^
$
在嵌入换行符前后立即匹配。这些是解析包含多个逻辑行的字符串的关键。
/g
修饰符告诉正则表达式引擎全局搜索所有匹配项

perl -0777 -ne 'print "$1 $2\n" while m{^(\S+).+?\[age=(\d+)\]}gms' file
给定如下输入文件:

01238584 (other info) more info, more info
[age=81][otherinfo][etc, etc]
98765432 (still other info) still more info, and more info
[age=82][and more otherinfo][etc, etc, ad infinitum]
…上面的脚本输出:

01238584 81
98765432 82
我们可以这样解析正则表达式:

perl -MYAPE::Regex::Explain -e 'print YAPE::Regex::Explain->new(qr/m{^(\S+).
+?[age=(\d+)}gms/)->explain()


使用sed和awk肯定有一种方法可以做到这一点,但是我给你的答案加1,因为用Python做这件事非常容易,而且非常人性化。就像他们说的:每次有人用sed或awk制作一个程序,一只小猫就死了。awk真让人讨厌!如果您遇到问题,还可以执行两步流程?关于
RS
的要点很好。我以前从未用过。经过30分钟的输入,我得到了适当的输出感谢1 grep+1 awk管道一起。也许不漂亮,但是。。输入也不是。我已经不再练习python了,所以我不知道如何填补这里的空白,但无论如何,非常感谢您分享您的回答!尽管我喜欢awk、sed和python,但我以前从未接触过perl,所以这很吸引人!令人印象深刻的是,你可以在一个相对较短的1班轮。谢谢你的解释!哦,这有点神秘,但不是不雅。
perl -MYAPE::Regex::Explain -e 'print YAPE::Regex::Explain->new(qr/m{^(\S+).
The regular expression:

(?-imsx:m{^(\S+).+?\[age=(\d+)\]}gms)

matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  m{                       'm{'
----------------------------------------------------------------------
  ^                        the beginning of the string
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    \S+                      non-whitespace (all but \n, \r, \t, \f,
                             and " ") (1 or more times (matching the
                             most amount possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
  .+?                      any character except \n (1 or more times
                           (matching the least amount possible))
----------------------------------------------------------------------
  \[                       '['
----------------------------------------------------------------------
  age=                     'age='
----------------------------------------------------------------------
  (                        group and capture to \2:
----------------------------------------------------------------------
    \d+                      digits (0-9) (1 or more times (matching
                             the most amount possible))
----------------------------------------------------------------------
  )                        end of \2
----------------------------------------------------------------------
  \]                       ']'
----------------------------------------------------------------------
  }gms                     '}gms'
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------