filename~contenturl~uuid~nodeid~contentid
000224.pdf~store://2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin~d6203724-1100-4057-9ed5-4ca6a94f5512~1324625~1363256
000238.pdf~store://2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin~96b7343d-349d-4316-8bc6-def5bd924032~1324641~1363292
000262.pdf~store://2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin~11827eee-67bb-43b7-a743-966514f26457~1324661~1363375
上面是我的 .csv 文件,分隔符为“~”,我想对从 store:// 开始的第二列进行子字符串操作,并希望将该行的校验和结果添加到同一列中的新列如果可能的话,使用 CSV。
例如
filename~contenturl~checksum
000224.pdf /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin 23423423425
因此,如果您看到最终结果,我会在 store:// 中对路径进行子串和处理,并添加该文件的一个名为 checksum 的新列。
我想通过 shell 脚本使用 bin/bash
======================= 就我而言,我只是尝试使用 AWK 并且只能使用以下方法获取第一列和第二列值
awk -F "~" '{print $1, $2}' $csv_file
现在接下来的事情对我来说很复杂,第二列值需要文本处理和校验和你可以通过
cksum /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin
是的,你没听错,最终结果看起来像
filename~contenturl~checksum
000224.pdf /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin 23423423425
如果我们有的话,其他栏的其余部分会更好,否则上面三栏也可以。 注意:如果保留现有列并添加更多名为“checksum”的列也可以。
答案1
为了使解决方案更容易一些,并且由于标题行不一致(输入文件中的换行符和~
输出文件中的分隔符错误),我们假设您的输入文件不包含标题行。
您可以分两步解决该任务:
创建一个
checksums.csv
文件,我们只需要文件的路径:awk -F'~' '{ system("cksum /opt/xyz"substr($2,8)) }' file.csv > checksums.csv
删除
substr($2,8)
前缀store:/
并/opt/xyz
添加到前面以完成路径。该system(…)
命令在给定路径上执行cksum
命令,并将输出重定向到输出文件。示例输出如下所示:
$ cat checksums.csv 128361894 41 /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin 820470222 41 /opt/xyz/2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin 1593587341 41 /opt/xyz/2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin
由于输出包含三列校验和、字节计数和路径,因此我们需要在下一步中提取第三列和第一列。
打印标题行并将 的column1(文件名)
file.csv
与 的column3(路径)和column1(校验和)合并checksums.csv
。{ echo "filename contenturl checksum";\ paste -d ' ' <(awk -F'~' '{ print $1 }' file.csv) <(awk '{ print $3,$1 }' checksums.csv);\ } > newfile.csv
输出示例:
$ cat newfile.csv filename contenturl checksum 000224.pdf /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin 128361894 000238.pdf /opt/xyz/2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin 820470222 000262.pdf /opt/xyz/2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin 1593587341
然后,清理:
rm checksums.csv
答案2
GNUsed
有e
命令标志s
,允许您像cksum
在脚本中一样集成 shell 处理:
sed -E 'h;s_.*~store:/([^~]*).*_cksum /opt/xyz\1_e;x;G;s_~[^~]*(.*)\n(.*) .* (.*)_~\2~\3\1_;s/~/ /g'
- 选项
-E
切换到扩展正则表达式以获得更好的可读性 h
将当前行保存在保留空间中,这样我们就可以随意搞乱它s_.*~store:/([^~]*).*_cksum /opt/xyz\1_e
匹配所有内容,包括store:/
(要删除)、()
要重用的文件名\1
以及该行的其余部分(要删除),并将其替换为cksum
+ 路径。现在e
标志开始执行此命令并用返回的内容替换模式空间x;G
交换保持和模式空间,然后将保持附加到模式空间,因此缓冲区包含s_~[^~]*(.*)\n(.*) .* (.*)_~\2~\3\1_
可能必须阅读,但易于编写:~[^~]*
是第二个字段、(.*)\n
原始行的其余部分以及(.*) .* (.*)
返回的三个字段cksum
,因此第二个字段被文件名和校验和替换- 您没有将其写在问题中,但在示例中没有
~
分隔符,而是两个空格:s/~/ /g