当正则表达式匹配内容时检索文件名
Retrieve file name when regexp matches content
所以我有一个包含一堆文本文件的目录,在每个文件中都有一行包含文件的时间戳,格式为:
TimeStamp: mm/dd/yyyy
我正在编写一个接受 3 个输入的脚本:月份、日期和年份,我想检索时间戳与输入匹配的文件的名称。
我正在使用这行代码来匹配文件并将找到的所有行输出到另一个文件。
egrep 'TimeStamp: ""/""/""' inFile > outFile
但是,我还没有想出在这个过程中获取文件名的方法。
另外,我相信有一种快速简单的方法可以用 awk 做到这一点,但我是 awk 的新手,所以我仍在努力。
grep -l
说明
-l, --files-with-matches
Suppress normal output; instead print the name of each input file from which
output would normally have been printed. The scanning will stop on the first
match. (-l is specified by POSIX.)
注:
- 我假设您想同时捕获匹配行,并且分别捕获具有匹配项的文件的名称(路径)(因此,仅使用
egrep -l
是 而不是 够了)。
- 根据您的问题,我已将
'TimeStamp: ""/""/""'
更改为 "TimeStamp: //"
,因为前者会将 </code>, ... 视为 <em> 文字</em>(不会扩展它们),因为被包含在 <em> 单 </em> 引号字符串中。</li>
</ul>
<p>如果您已经有一个 <em> 单个 </em> 文件名要传递给 <code>egrep
,您可以使用 &&
有条件地输出该文件名 if 该文件包含匹配项(在 除了 捕获文件中的匹配项之外)。
egrep "TimeStamp: //" inFile > outFile && printf '%s\n' inFile
处理整个目录时,简单且POSIX兼容但效率低下的方法是处理文件在循环中:
for f in *; do
[ -f "$f" ] || continue # skip non-files or break, if dir. is empty
egrep "TimeStamp: //" "$f" >> outFile && printf '%s\n' "$f"
done
如果你使用bash
和GNUgrep
或BSDgrep
(也用于OSX),有一个更高效的解决方案:
egrep -sH "TimeStamp: //" * |
tee >(cut -d: -f1 | sort -u > outFilenames) |
cut -d: -f2- > outFile
- 因为
*
也可能匹配 目录 ,-s
抑制了由于(总是失败)尝试将它们处理为 的错误消息文件.
-H
确保每个匹配行都以输入文件名为前缀,后跟 :
tee >(...) ...
将输入同时发送到标准输出和 >(...)
. 中的命令
cut -d: -f1 | sort -u
从结果行中提取匹配的文件名,创建一个没有重复的排序列表,并将它们发送到文件 outFilenames
.
cut -d: -f2-
然后提取匹配的行(去掉它们的文件名前缀)并将它们捕获到文件 outFile
. 中
所以我有一个包含一堆文本文件的目录,在每个文件中都有一行包含文件的时间戳,格式为:
TimeStamp: mm/dd/yyyy
我正在编写一个接受 3 个输入的脚本:月份、日期和年份,我想检索时间戳与输入匹配的文件的名称。
我正在使用这行代码来匹配文件并将找到的所有行输出到另一个文件。
egrep 'TimeStamp: ""/""/""' inFile > outFile
但是,我还没有想出在这个过程中获取文件名的方法。 另外,我相信有一种快速简单的方法可以用 awk 做到这一点,但我是 awk 的新手,所以我仍在努力。
grep -l
说明
-l, --files-with-matches Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match. (-l is specified by POSIX.)
注:
- 我假设您想同时捕获匹配行,并且分别捕获具有匹配项的文件的名称(路径)(因此,仅使用
egrep -l
是 而不是 够了)。 - 根据您的问题,我已将
'TimeStamp: ""/""/""'
更改为"TimeStamp: //"
,因为前者会将</code>, ... 视为 <em> 文字</em>(不会扩展它们),因为被包含在 <em> 单 </em> 引号字符串中。</li> </ul> <p>如果您已经有一个 <em> 单个 </em> 文件名要传递给 <code>egrep
,您可以使用&&
有条件地输出该文件名 if 该文件包含匹配项(在 除了 捕获文件中的匹配项之外)。egrep "TimeStamp: //" inFile > outFile && printf '%s\n' inFile
处理整个目录时,简单且POSIX兼容但效率低下的方法是处理文件在循环中:
for f in *; do [ -f "$f" ] || continue # skip non-files or break, if dir. is empty egrep "TimeStamp: //" "$f" >> outFile && printf '%s\n' "$f" done
如果你使用
bash
和GNUgrep
或BSDgrep
(也用于OSX),有一个更高效的解决方案:egrep -sH "TimeStamp: //" * | tee >(cut -d: -f1 | sort -u > outFilenames) | cut -d: -f2- > outFile
- 因为
*
也可能匹配 目录 ,-s
抑制了由于(总是失败)尝试将它们处理为 的错误消息文件. -H
确保每个匹配行都以输入文件名为前缀,后跟:
tee >(...) ...
将输入同时发送到标准输出和>(...)
. 中的命令
cut -d: -f1 | sort -u
从结果行中提取匹配的文件名,创建一个没有重复的排序列表,并将它们发送到文件outFilenames
.cut -d: -f2-
然后提取匹配的行(去掉它们的文件名前缀)并将它们捕获到文件outFile
. 中
- 因为