【发布时间】:2018-08-29 13:09:45
【问题描述】:
我一直在编写一个脚本,将多个 csv 文件连接成一个大的 csv。 csv 包含文件夹的名称及其各自的大小,采用 2 列设置,格式为“大小,项目名称”
单个 csv 文件示例:
49747851728,ODIN
32872934580,_WORK
9721820722,LIBRARY
4855839655,BASELIGHT
1035732096,ARCHIVE
907756578,USERS
123685100,ENV
3682821,SHOTGUN
1879186,SALT
361558,SOFTWARE
486,VFX
128,DNA
对于我当前的测试,我有 25 个类似的文件,第一列中的数字不同。
我正在尝试让此脚本执行以下操作:
- 读取每个 csv 文件
- 对于它看到的每个项目,如果该项目已打印到文件中,请扫描输出文件。如果没有,请打印项目名称
- 对于每个文件,对于每个项目,如果找到项目,则将大小打印到输出 csv。
但是,我需要所有项目都在文本行 1 上,以逗号分隔,因此我可以将此输出文件用作 javascript 图形的输入。尺寸应添加到其项目名称下方的列中。
我当前的脚本:
csv_folder=$(echo "$1" | sed 's/^[ \t]*//;s/\/[ \t]*$//')
csv_allfiles="$csv_folder/*.csv"
csv_outputfile=$csv_folder.csv
echo -n "" > $csv_outputfile
for csv_inputfile in $csv_allfiles; do
while read line && [[ $line != "" ]]; do
projectname=$(echo $line | sed 's/^\([^,]*\),//')
projectfound1=$(cat $csv_outputfile | grep -w $projectname)
if [[ ! $projectfound1 ]]; then
textline=1
sed "${textline}s/$/${projectname}, /" >> $csv_outputfile
for csv_foundfile in $csv_allfiles; do
textline=$(echo $textline + 1 | bc )
projectfound2=$(cat $csv_foundfile | grep -w $projectname)
projectdata=$(echo $projectfound2 | sed 's/\,.*$//')
if [[ $projectfound2 ]]; then
sed "${textline}s/$/$projectdata, /" >> $csv_outputfile
fi
done
fi
done < $csv_inputfile
done
我当前的脚本找到了正确的信息(项目名称、项目数据),如果我只是“回显”这些变量,它会将正确的数据打印到文件中。但是,使用 echo 它只会在每个项目中打印出很长的列表。我希望它“跳回”到第 1 行并在当前行的末尾打印新项目,然后运行循环以在每个下一行的末尾打印数据。
我认为这应该可以通过 sed 或 awk 实现。 sed 应该有一种使用
将文本插入特定行的方法sed '{n}s/search/replace/'
其中 {n} 是要插入的行
awk 应该能够用类似
的东西做同样的事情awk -v l2="$textline" -v d="$projectdata" 'NR == l2 {print d} {print}' >> $csv_outputfile
但是,将脚本中的 sed 命令替换为
echo $projectname
echo $projectdata
吐出正确的信息(所以我知道我的变量填写正确) sed 和 awk 命令倾向于吐出它们当前 inputcsv 的全部内容;不只是我希望他们这样做。
Pastebin 输出每个写入文件的变体
- https://pastebin.com/XwxiAqvT - sed 输出
- https://pastebin.com/xfLU6wri - 回显,普通输出(单列)
- https://pastebin.com/wP3BhgY8 - 回显,每个变量的详细输出
- https://pastebin.com/5wiuq53n - 想要的输出
如您所见,sed 输出倾向于粘贴 inputcsv 的全部内容,使循环在一次迭代后停止。 (因为它会在一个循环后找到其他项目)
所以我的问题就是其中之一;
- 如何使 sed / awk 以我希望的方式运行;即仅将我的 var 中的信息打印到当前文本行,而不是整个输入 csv。 sed 能做到这一点,只打印一行变量吗?或者
- 我是否应该通过“echo”将变量输出到一个临时文件中,然后遍历该临时文件以使 sed 按我希望的方式对行进行排序? (请记住,将来会添加更多 .csv 文件,我不能让它循环 x 次来对信息进行排序)
- 有没有一种方法可以在不使用 sed 或 awk 的情况下将文本回显/打印到特定的文本行?是否有我缺少的 printf 选项?其他想法?
非常感谢任何帮助。
【问题讨论】:
-
这是一个 X-Y 问题。您正在尝试解决由您的解决方案选择引起的问题。除了连接文件之外,我还不清楚您要做什么?一个项目是否在多个文件中?如果是这样,您是否将尺寸相加?或者,选择第一个?给定输入文件的预期输出是什么?
-
无论你想做什么,用一个小的 awk 脚本来解决都非常简单,但我们无法判断你想做什么,因为你没有提供清楚的说明,简洁,可测试的样本输入和预期输出。只需这样做,您就会得到答案。
-
我真的不知道我的请求不清楚。我的帖子顶部附近给出了一个示例输入。我有很多 csv 文件,其中包含一个包含“大小,文件夹名称”格式的文件夹大小的列表。我希望这些文件夹以列的形式显示,它们的大小在它们下方,我的文件夹中的每个 .csv 文件占一行。期望的输出:pastebin.com/5wiuq53n 我也会将该 pastebin 添加到我的原始帖子中。