使用 sed 的正则表达式搜索对文件中的条目进行排序

使用 sed 的正则表达式搜索对文件中的条目进行排序

我有一个以下形式的文本文件:

dir1/sub-dir1/.../filename1 author date
dir1/sub-dir1/.../filename2 author date
.
.
.
dir2/sub-di2/.../filename1 author date
dir2/sub-dir2/.../filename2 author date

额外细节:

  • 列出的每个文件名恰好存在 1 次或 2 次。也就是说,filename_n恰好存在 1 次或 2 次。如果它存在 1 次,则它仅存在于我们软件的 1 个版本中,即 v1 或 v2,具体取决于路径。如果存在2次,则该文件同时是v1和v2。
  • 该路径确定文件是 v1 还是 v2。
  • 文本文件以制表符分隔。
  • 子目录的数量因文件而异(因此...在代码块中)。
  • (作者和日期不是从 中获取的ls。它们是通过询问最后记录对这些文件的更改的 git 提交而单独生成的。)

我尝试使用 sed 和正则表达式来转换文件,使其看起来像这样:

dir1/sub-dir1/.../filename1 author date dir2/sub-di2/.../filename1 author date
dir1/sub-dir1/.../filename2 author date dir2/sub-dir2/.../filename2 author date
.
.
.

如果filename-n没有匹配项,则它应该只出现一次,而不是两次。

我正在寻找一种使用 sed 和正则表达式来执行转换的方法。它可以写入同一个文件(使用-i),也可以写入单独的文件。

答案1

可以完全使用 来完成此操作sed,但这会导致难以理解的复杂脚本,因此我建议先按文件名对文件进行排序,然后sed在发现文件名两次时使用 来连接行。

文件名位于第三个子目录中,我们告诉我们sort使用第四个字段 ( -k 4) 和\(到底为什么!!)作为字段分隔符:

sort -t'\' -k 4 /tmp/p|sed 'N;/\(\\[^\]*        \).*\1/s/\n/    /;P;D'

sed命令使用典型的N;P;D循环来始终一次处理两行并检查文件名(在\TAB 之间)是否重复。

请注意,脚本中有两个文字选项卡sed。使用 GNU sed,你可以\t这样写:

sort -t'\' -k 4 /tmp/p|sed 'N;/\(\\[^\]*\t\).*\1/s/\n/\t/;P;D'

另请注意,包含制表符或反斜杠的路径可能会破坏脚本。

答案2

在每个 Unix 机器上的任何 shell 中使用任何 awk,无论您的路径包含哪些字符(换行符除外):

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
    file = $0
    sub(".*/","",file)
    paths[file] = (file in paths ? paths[file] OFS : "") $0
}
END {
    for ( file in paths ) {
        print paths[file]
    }
}

$ awk -f tst.awk file
dir1/sub-dir1/.../filename2 author date dir2/sub-dir2/.../filename2 author date
.       .       .
dir1/sub-dir1/.../filename1 author date dir2/sub-di2/.../filename1 author date

如果输出顺序确实很重要,那么这是一个微不足道的调整 - 只需告诉我们输出顺序应该是什么(例如首先读取,按文件名字母顺序,按目录字母顺序,其他)。

相关内容