grep多列,为了还是awk更好?

时间:2014-09-08 02:03:50

标签: bash awk grep

Linux Debian Testing 64。

我希望grep或awk以下......

ExifListAll =(下方)

DSCF3566.JPG    2014-07-21 12:54:32 On  1
DSCF3566.RAF    2014-07-21 12:54:32 On  1
DSCF3567.JPG    2014-07-21 12:54:33 On  2
DSCF3567.RAF    2014-07-21 12:54:33 On  2
DSCF3568.JPG    2014-07-21 12:54:33 On  3
DSCF3568.RAF    2014-07-21 12:54:33 On  3
DSCF3569.JPG    2014-07-21 12:54:34 Off 0

我将使用第3列时间12:54:33开始,之前搜索1秒,之后搜索1秒, 第4栏="开"和第5列= 1,2或3

到目前为止我已尝试过这个;

echo "$ExifListAll" | grep -E '2014-07-21.*12:45:3[3-4].*On.*[1-3]'

我能否更有效地使用awk 1衬垫?

我这样做是否正确?

echo "$ExifListAll" | awk '$4 == "On" && $5~/1/,$5~/3/'

谢谢。

3 个答案:

答案 0 :(得分:1)

grep可以正常使用。您只是对语法提出了挑战。首先,使用模式\s*来匹配字段之间的零个或多个空格更容易。您正在使用.*(因为正则表达式是贪婪的)将匹配每个字符到行尾。此外,字符类表示包含在其中的字符。即要匹配1,2或3,请使用[123]。通过这些更改,以下内容可以实现您的意图:

echo "$ExifListAll" | grep -E "2014-07-21\s*12:54:3[34]\s*On\s*[123]"

<强>输出:

$ cat grepdat.dat | grep -E "2014-07-21\s*12:54:3[34]\s*On\s*[123]"
DSCF3567.JPG    2014-07-21 12:54:33 On  2
DSCF3567.RAF    2014-07-21 12:54:33 On  2
DSCF3568.JPG    2014-07-21 12:54:33 On  3
DSCF3568.RAF    2014-07-21 12:54:33 On  3

这不是您期望的输出吗? 12:54:34有Off&amp;一个0,我从你的问题中解释为不想要的。如果您希望状态On/Off regardless, and included the 0`对应于12:54:34关0,则使用:

echo "$ExifListAll" | grep -E "2014-07-21\s*12:54:3[34]\s*(On|Off)\s*[0123]"

<强>输出:

$ cat grepdat.dat | grep -E "2014-07-21\s*12:54:3[34]\s*(On|Off)\s*[0123]"
DSCF3567.JPG    2014-07-21 12:54:33 On  2
DSCF3567.RAF    2014-07-21 12:54:33 On  2
DSCF3568.JPG    2014-07-21 12:54:33 On  3
DSCF3568.RAF    2014-07-21 12:54:33 On  3
DSCF3569.JPG    2014-07-21 12:54:34 Off 0

每条评论需要第1-6行:

cat grepdat.dat | grep -E "2014-07-21\s*12:54:3[234]\s*On\s*[123]"

<强>输出

$ cat grepdat.dat | grep -E "2014-07-21\s*12:54:3[234]\s*On\s*[123]"
DSCF3566.JPG    2014-07-21 12:54:32 On  1
DSCF3566.RAF    2014-07-21 12:54:32 On  1
DSCF3567.JPG    2014-07-21 12:54:33 On  2
DSCF3567.RAF    2014-07-21 12:54:33 On  2
DSCF3568.JPG    2014-07-21 12:54:33 On  3
DSCF3568.RAF    2014-07-21 12:54:33 On  3

答案 1 :(得分:1)

您不能使用范围或标志来检索与/ end / block匹配的多个行。对于使用awk的更通用的解决方案,您可以将时间转换为纪元时间,然后设置比较:

mydatetime="2014-07-21 12:54:33"
awk -v expected_time=$(date -d"$mydatetime" +%s) '
  { t = $2" "$3; gsub(/[:-]/," ",t); t1 = mktime(t) }
  t1 >= expected_time-1 && t1 <= expected_time+1 && $4 =="On" && $5 ~ /^[123]$/
' file.txt

注意:

  1. 第1行:使用-v expected_time = $(...)
  2. 将expected_time设置为纪元时间戳
  3. 将每个记录的入场时间($ 2&#34;&#34; $ 3)转换为格式&#34; YYYY mm dd HH MM SS&#34;然后输入mktime()以使用awk生成纪元时间戳。
  4. 比较时间并确保$ 4是&#39; On&#39; 5美元是1,2或3。
  5. 如果你完全知道你提到的expected_time,那么只需使用你的grep线,比awk更简单,更快。

    grep -E '2014-07-21.*12:54:3[2-4].*On.*[1-3]' file.txt
    

答案 2 :(得分:0)

谢谢大家的建议。

我使用了另一种更直接的方法,使用了“exiftool&#39; 它从图像中读取所有元数据。

我选择了目录中的任何图像,然后给出前一秒和下一秒。 我还不确定如何替换所提供的信息,但我会从你的帮助中解决这个问题。

DateTimeOrigFirst="$(exiftool -T -d '%F %T' -DateTimeOriginal DSCF3567.RAF)"
DateTimeOrig1SecMinus="$(exiftool -T -globalTimeShift "-0:0:0 0:0:1" -d '%F %T' -DateTimeOriginal DSCF3567.RAF)"
DateTimeOrig1SecPlus="$(exiftool -T -globalTimeShift "+0:0:0 0:0:1" -d '%F %T' -DateTimeOriginal DSCF3567.RAF)"

然后我可以在第一个例子中使用;

生成图像1-6
printf %s\\n "$ExifListAll" | tr '\t' ' ' | grep \
-E "$DateTimeOrigFirst|$DateTimeOrig1SecMinus|$DateTimeOrig1SecPlus"

再次感谢。