使用带有sed的正则表达式在unix中过滤文件

时间:2014-02-12 15:45:17

标签: regex shell unix sed

我正在记录我的作业服务器的Shell脚本,它采用一系列以“dat”开头的文件,并对所有这些文件执行特定任务。问题是该脚本使用带有sed命令的正则表达式过滤文件,如下所示:

namecmp=`grep -l $name dat*.p |sed -e "s/^\(......\)\(..\)\(..\)\(....\)\(.*\)/\1\4\3\2\5/g"| sort -t '.' -k 1.7,1.14 |sed -e "s/^\(......\)\(....\)\(..\)\(..\)\(.*\)/\1\4\3\2\5/g" | tail -1 `

我不明白这个正则表达式是如何过滤掉文件的。知道由该表达式过滤的任何预期输出或示例文件将是有帮助的。

有没有办法找到该表达式接受的可能表达式?

3 个答案:

答案 0 :(得分:3)

grep -l在文件列表(dat*.p)中搜索正则表达式($name,或者更好:$name评估为什么)然后打印只有找到它的文件名。

这些文件名然后通过sed命令传递,该命令替换s代替某些东西,即^\(......\)\(..\)\(..\)\(....\)\(.*\) \1\4\3\2\5(所以它只重新组合部分文件名)。然后,转换后的文件名将传递给sort,然后再传递给sed,这似乎取消了重新组合文件名。

最后,只取最后一个文件名(tail -1),其余所有文件都被丢弃。这比通过对所有文件名进行排序要便宜得多,但是谁在乎; - )

实际上,此行找到与$name中的正则表达式匹配的“last”文件的名称。 “last”的含义取决于重新组合后文件名的排序;假设从组的大小,我认为时间戳被修改,以便它从DDMMYYYY更改为YYYYMMDD,这在某种程度上是有意义的。

答案 1 :(得分:1)

有设计用于实现这一目标的库(例如 Xeger),但为此我可以为您提供一个示例:

abcdef02122014foobarfoobarfoobar
^     ^ ^ ^   ^
|     | | |   |
1     2 3 4   5

变为

abcdef20140212foobarfoobarfoobar
^     ^   ^ ^ ^
|     |   | | |
1     4   3 2 5

然后我不知道sort做了什么,但下一个sed只是将上述所有内容都按顺序排列。

因此,在恢复原始格式之前,似乎正则表达式用于临时更改行的格式以进行排序。

答案 2 :(得分:0)

echo "1111112233444456789" | sed -e "s/^\(......\)\(..\)\(..\)\(....\)\(.*\)/\1\4\3\2\5/g"

-> 1111114444332256789

解释

Begin   111111    22    33    4444    56789
^     \(......\)\(..\)\(..\)\(....\)\(.*\)
        \1        \2    \3    \4      \5

优化:

  • 不需要最后\(.*\),因此必须删除相应的\5
  • 也不需要最后一个g^只有一次替换,意味着字符串的开头