合并 git BASH 中多个 CSV 文件的第二列
Merging the second column of multple CSV files in git BASH
我正在尝试将一个文件夹中多个 CSV 文件的所有第二列合并为一个 CSV 文件(按列)。我失败了。当我尝试合并剪切第一列时它起作用(通过放置 -f1)但是当我尝试使用第二列(-f2)时它只会弄得一团糟。想不通为什么。这是我的代码
for i in $FILES;
do
paste -d, final_table.csv <(cut -d',' -f 2 --complement "$i") > final_table_intermediate.csv; mv final_table_intermediate.csv final_table.csv ;
done
提前致谢
埃米利亚诺
我会看一下 @hayden-schiff
建议的 csvkit
如果您不想走那条路,这就是我想出的办法。
尽管有一些注意事项:
更新:您的编辑显示您的输入文件并不总是有两列,我还没有找到制作cut
[=57=的方法] 一个空字符串(但带有换行符)以使旧版本工作。
所以现在我逐行浏览 CSV,将值(或空字符串)抓取到每个输入文件的临时文件中,然后在最后将它们全部粘贴在一起:
#!/usr/bin/env bash
FILES="infile_??.csv"
FINAL="final_table.csv"
COLUMN="3"
# Delete ${FINAL} if it exists.
[[ -f "${FINAL}" ]] && rm ${FINAL}
TMPFILES=""
for f in ${FILES}; do
while IFS='' read -r line || [[ -n "$line" ]]; do
val=$(cut -f ${COLUMN} -d, -s <<< $line)
[[ -n "${val}" ]] && echo "${val}" || echo " "
done < "${f}" > "${f}.${COLUMN}.csv"
TMPFILES="${TMPFILES} ${f}.${COLUMN}.csv"
done
paste -d, ${TMPFILES} > ${FINAL}
rm ${TMPFILES}
以下是我的原始版本,它假设所有文件确实至少有您想要阅读的列数:
- 对我的解决方案不满意,因为您一遍又一遍地打开同一个文件以同时读取和写入。我很想知道有一种方法可以将未知数量的进程的输出作为不同的输入流传递到单个最终进程中。
- 在您的描述中您想要第二列,但是您使用了
--complement
选项,其中 return 包含 除第二列之外的所有内容 。这让我有点反感。我忽略了这一点,按照你的描述去做。
这里是:
#!/usr/bin/env bash
FILES="infile_??.csv"
FINAL="final_table.csv"
COLUMN="2"
# Delete ${FINAL} if it exists.
[[ -f "${FINAL}" ]] && rm ${FINAL}
for f in $FILES; do
if [[ -f ${FINAL} ]]; then
# ${FINAL} already exists from an earlier iteration
# If you have "moreutils" installed, you can use sponge:
# cut -d',' -f 2 ${f} | paste -d',' ${FINAL} - | sponge ${FINAL}
# otherwise you can use "echo" in the way below:
echo "$(cut -d',' -f ${COLUMN} ${f} | paste -d',' ${FINAL} -)" > ${FINAL}
else
# ${FINAL} does not yet exist, we have to create it.
cut -d',' -f ${COLUMN} ${f} > ${FINAL}
fi
done
更新:我的理解是它应该取每个输入文件的第二列,并将它们逐列写入输出文件,如下所示:
我的输入文件:
infile_01.txt
:
111, 112, 113
121, 122, 123
131, 132, 133
141, 142, 143
infile_02.txt
:
211, 212, 213
221, 222, 223
231, 232, 233
241, 242, 243
(所以每个数字是 100 *(文件编号)+ 10 *(行号)+(列号)。)
我的代码在我的电脑上产生了这个输出:
112, 212
122, 222
132, 232
142, 242
如果这是您得到的但不是您想要的,请告诉我这些输入文件的输出文件应该是什么样子。如果这不是您得到的,请 运行 在您的系统上使用我的文件并告诉我您得到了什么。
我正在尝试将一个文件夹中多个 CSV 文件的所有第二列合并为一个 CSV 文件(按列)。我失败了。当我尝试合并剪切第一列时它起作用(通过放置 -f1)但是当我尝试使用第二列(-f2)时它只会弄得一团糟。想不通为什么。这是我的代码
for i in $FILES;
do
paste -d, final_table.csv <(cut -d',' -f 2 --complement "$i") > final_table_intermediate.csv; mv final_table_intermediate.csv final_table.csv ;
done
提前致谢 埃米利亚诺
我会看一下 @hayden-schiff
建议的 csvkit如果您不想走那条路,这就是我想出的办法。 尽管有一些注意事项:
更新:您的编辑显示您的输入文件并不总是有两列,我还没有找到制作cut
[=57=的方法] 一个空字符串(但带有换行符)以使旧版本工作。
所以现在我逐行浏览 CSV,将值(或空字符串)抓取到每个输入文件的临时文件中,然后在最后将它们全部粘贴在一起:
#!/usr/bin/env bash
FILES="infile_??.csv"
FINAL="final_table.csv"
COLUMN="3"
# Delete ${FINAL} if it exists.
[[ -f "${FINAL}" ]] && rm ${FINAL}
TMPFILES=""
for f in ${FILES}; do
while IFS='' read -r line || [[ -n "$line" ]]; do
val=$(cut -f ${COLUMN} -d, -s <<< $line)
[[ -n "${val}" ]] && echo "${val}" || echo " "
done < "${f}" > "${f}.${COLUMN}.csv"
TMPFILES="${TMPFILES} ${f}.${COLUMN}.csv"
done
paste -d, ${TMPFILES} > ${FINAL}
rm ${TMPFILES}
以下是我的原始版本,它假设所有文件确实至少有您想要阅读的列数:
- 对我的解决方案不满意,因为您一遍又一遍地打开同一个文件以同时读取和写入。我很想知道有一种方法可以将未知数量的进程的输出作为不同的输入流传递到单个最终进程中。
- 在您的描述中您想要第二列,但是您使用了
--complement
选项,其中 return 包含 除第二列之外的所有内容 。这让我有点反感。我忽略了这一点,按照你的描述去做。
这里是:
#!/usr/bin/env bash
FILES="infile_??.csv"
FINAL="final_table.csv"
COLUMN="2"
# Delete ${FINAL} if it exists.
[[ -f "${FINAL}" ]] && rm ${FINAL}
for f in $FILES; do
if [[ -f ${FINAL} ]]; then
# ${FINAL} already exists from an earlier iteration
# If you have "moreutils" installed, you can use sponge:
# cut -d',' -f 2 ${f} | paste -d',' ${FINAL} - | sponge ${FINAL}
# otherwise you can use "echo" in the way below:
echo "$(cut -d',' -f ${COLUMN} ${f} | paste -d',' ${FINAL} -)" > ${FINAL}
else
# ${FINAL} does not yet exist, we have to create it.
cut -d',' -f ${COLUMN} ${f} > ${FINAL}
fi
done
更新:我的理解是它应该取每个输入文件的第二列,并将它们逐列写入输出文件,如下所示:
我的输入文件:
infile_01.txt
:
111, 112, 113
121, 122, 123
131, 132, 133
141, 142, 143
infile_02.txt
:
211, 212, 213
221, 222, 223
231, 232, 233
241, 242, 243
(所以每个数字是 100 *(文件编号)+ 10 *(行号)+(列号)。)
我的代码在我的电脑上产生了这个输出:
112, 212
122, 222
132, 232
142, 242
如果这是您得到的但不是您想要的,请告诉我这些输入文件的输出文件应该是什么样子。如果这不是您得到的,请 运行 在您的系统上使用我的文件并告诉我您得到了什么。