Haven没有看到类似的解决方案......
我有两个文件,每个文件都包含一个文件名列表。文件内容有重叠,但文件A包含文件B中不存在的文件名。另外,文件A和B中的文件扩展名不同。即:
A B
------------ --------------
file-1-2.txt file-1-2.png
file-2-3.txt file-3-4.png
file-3-4.txt
...
如何将逗号分隔的两个文件合并为一个忽略不匹配的行?
那是:
C
------------
file-1-2.txt,file-1-2.png
file-3-4.txt,file-3-4.png
我认为类似于以下内容的awk
的一些用法将起作用:
awk 'FNR==NR{NOT SURE} {print $1,$2}' fileA fileB
提前致谢!
答案 0 :(得分:2)
这个纯粹的bash解决方案应该能够处理并处理任一文件中的点,反斜线,破折号和其他特殊字符。
mapfile -t arr_a < A
mapfile -t arr_b < B
for a in "${arr_a[@]}"; do for b in "${arr_b[@]}"; do
[[ ${a%.*} == "${b%.*}" ]] && printf '%s,%s\n' "$a" "$b" && break
done; done
首先,我们使用mapfile
将文件内容读入数组,每个项目一行。 1 然后,对于A
中的每一行,我们将与B
中的每一行进行比较。
为了仅比较扩展之前的部分,我们使用shell参数扩展${var%pattern}
,它从结束时删除了glob .*
2 的最短匹配。文件名。
1 -t选项从数组项中删除尾部换行符。
2 这里的.
是文字的,删除了一个句号和之后的所有内容。
答案 1 :(得分:1)
你可以这样做:
$ awk 'function base(fn) {sub("[.][^.]*$", "", fn); return fn}
NR==FNR { fn[$1]; next}
{for (e in fn){ if (base(e)==base($1)){ printf "%s,%s\n", e, $1 }}} ' f1 f2
file-1-2.txt,file-1-2.png
file-3-4.txt,file-3-4.png
由于awk
关联数组是无序的,因此打印输出的顺序由第二个文件的顺序决定 - 而不是第一个。
说明:
function base(fn) {sub("[.][^.]*$", "", fn); return fn}
是一个从文件名中删除扩展名的函数(假设扩展名是找到的最后一个.
右侧的非.
个字符。返回整个名称如果没有找到.
。)NR==FNR { fn[$1]; next}
将每一行(在本例中为每个文件名)读入一个关联数组。 NR==FNR
是awk
成语,仅对第一个文件为真,next
表示在第一个文件名文件上执行此部分。由于前导和尾随空格被剥离,因此使用$1
。由于Unix文件名可以具有前导或尾随空格,因此这是您需要解决的罕见歧义。如果您不想剥离线条,则可以使用$0
代替。{for (e in fn){ if (base(e)==base($1)){ printf "%s,%s\n", e, $1 }}}
现在用于除第一个文件以外的任何行(其中NR==FNR
为真,因为next
跳过此部分)循环保存的文件名。如果基本名称相同则打印。 答案 2 :(得分:0)
unix join命令应该做你想要的。设置字段分隔符-t'。'成为一个点并通过两个文件中的第一列连接。您可能需要提前对文件进行排序。可以使用正确的语法在与连接相同的命令行上完成排序。 &lt;(sort -k 2 file1.txt)&lt;(sort file2.txt)
答案 3 :(得分:0)
这是一种相当强大的力量:
file1="file1.txt"
file2="file2.txt"
out_file="out.txt"
touch $out_file
while read line ; do # read the first file line by line
file1_name="$(echo "$line" | cut -d'.' -f1)" # get the filename without extension
file2_name="$(grep "$file1_name\." $file2)"
if [ -n "$file2_name" ]; then #did we find a match
echo "$line,$file2_name" >> $out_file
else
echo "Did not find a match to ${line} in $file2"
fi
done < $file1
我们遍历file1并在文件2中查找匹配项。如果找到,我们输出到输出文件。
其他改进:使用正则表达式更好的grep:
file2_name="$(grep -e "$file1_name\.[^.]*$" $file2)"
这会查找以$file1_name
开头的一行,一个点.
,然后不再有点,直到结尾为扩展名。