我有两个文件,我想生成一个新文件,其中包含在 中找到file2
但不在file1
.原始文件未排序。
现在,这是棘手的部分。文件中的某些行遵循以下格式:
./$ARTIST/$ALBUM/$N1 - $N2 - $TITLE.(flac|mp3)
./$ARTIST/$ALBUM/$N1 - $TITLE.(flac|mp3)
./$ARTIST/$ALBUM/$N1. $TITLE.(flac|mp3)
其中$N1
和$N2
是 1-3 位长度的数字,例如01
, 12
,132
$ARTIST
,$ALBUM
并且$TITLE
可以由任何字母数字字符序列组成,包括 .和 - 但不是 /。
flac
我希望以或结尾的行mp3
被视为匹配,如果$ARTIST
,$ALBUM
和$TITLE
相同,并且要排除相应的行。
例子file1
./The BEATLES/white album/01. Revo-lution.flac
./123-123/234-234/01 - 02 - 3769.flac
./THE BEATLES/abbey road/cover.jpg
例子file2
./The BEATLES/white album/01. Notinfile1.flac
./123-123/234-234/03. 3769.flac
./THE BEATLES/abbey road/cover.jpg
输出文件
./The BEATLES/white album/01. Notinfile1.flac
编辑:
我已经考虑过这个问题并提出了解决方案,但需要有人帮助我编码。
对于两个文件的每一行,可以使用以下方法生成密钥。随后对文件之间的键进行比较可用于输出键与中的键file2
不匹配的行file1
密钥生成如下:
如果行不以flac
或结尾mp3
,则键是行本身。
否则,检查第一次出现的.
或-
最后一次出现的/
.
如果.
是这种情况,那么关键是点后面的内容$ARTIST/$ALBUM/$TITLE
在哪里。$TITLE
如果-
是这种情况,则计算最后一个之后的行部分中的破折号数量/
。
如果找到了,那么关键是破折号后面的内容$ARTIST/$ALBUM/$TITLE
在哪里。$TITLE
如果找到多于或等于两个破折号,则检查第一个破折号和第二个破折号之间的内容是否纯粹是数字和空格。如果是,则$TITLE
在第二个破折号之后。如果不是,则$TITLE
在第一个破折号之后。
有人可以帮我编码吗?
答案1
当您想要比较文件时,按排序顺序排列文件通常很有用。通过删除任何重复项,使-u
输出中的每一行都是唯一的。
sort -u file1 > file1.sorted
sort -u file2 > file2.sorted
comm
可以比较排序的文件,但只能比较文字文本。所以这会减少问题但只能过滤掉精确匹配。-1
删除第一个文件特有的行并-3
删除两个文件参数共有的行。这给我们留下了第二个文件特有的行。
comm -1 -3 file1.sorted file2.sorted > file2.reduced
现在我们只需要为这个(希望)较小的文件做复杂的工作。
sed 's#^\./##' file2.reduced | while read line; do
artist_album=${line%/*}
filename=${line##*/}
title=$(echo "$filename" | sed 's/^[0-9]\{1,3\}\. //;t;s/^[0-9]\{1,3\} - [0-9]\{1,3\} - //;t;s/^[0-9]\{1,3\} - //')
extension=${title##*.}
title=${title%.$extension}
# We use fixed strings in case there are special chars in the file name
# If the file names are "regex-save" we can use one grep instead:
# ! grep -q -E "^\./$artist_album/.*$title\.(mp3|flac)\$" file1.sorted
if ! grep -F "./$artist_album/" file1.sorted | grep -F -e "$title." | grep -q -E '(mp3|flac)$'; then
echo "./$line"
fi
done > results