bash - 当值是多行时解析 CSV 记录
问题描述
源文件如下所示:
"google.com", "vuln_example1
vuln_example2
vuln_example3"
"facebook.com", "vuln_example2"
"reddit.com", "stupidly_long_vuln_name1"
"stackoverflow.com", ""
我一直试图让输出变成这样,但换行符似乎给我带来了无穷无尽的问题。我正在使用“读取时行”作业来执行此操作,因为我对列进行了一些处理(例如,本示例中的漏洞计数和 url)。这是输出到詹金斯作业(yuk)中。
问题的基本总结是让 csv 中的换行符输出到第三列,同时保留表结构。我在下面有一个所需输出的奇怪示例。
||hostname ||Vulnerability count|| Vulnerability list || URL ||
|google.com |3 |vuln_example1 |http://cve.com/vuln_example1|
| | |vuln_example2 |http://cve.com/vuln_example2|
| | |vuln_example3 |http://cve.com/vuln_example3|
|facebook.com |1 |vuln_example2 |http://cve.com/vuln_example2|
|reddit.com |1 |stupidly_long_vuln_name1 |http://cve.com/stupidly_long_vuln_name1|
|stackoverflow.com |0 | ||
看着这个......我有一种感觉,通过显示一些代码和示例输出可能会更容易。
解决方案
使用下面的命令行解析您的输入会使问题变得更容易(我假设输入是正确的):
perl -0777 -pe 's/([^"])\s*\n/\1 /g ; s/[",]//g' < sample.txt
此行调用 Perl 来执行两个正则表达式替换:
s/([^"])\s*\n/\1 /g
: 如果它没有以引号终止"
(即,如果主机条目,所有漏洞尚未完成),则此替换将删除行尾。s/[",]//g
删除所有剩余的引号和逗号。
对于像这样的每个主机条目:
"google.com", "vuln_example1
vuln_example2
vuln_example3"
你会得到:
google.com vuln_example1 vuln_example2 vuln_example3
然后你可以假设每一行都有一个主机和一组漏洞。
下面给出的示例将漏洞存储在一个数组中并循环遍历它,格式化和打印每一行:
# Replace this by your custom function
# to get an URL for a given vulnerability
function get_vuln_url () {
# This just displays a random url for an non-empty arg
[[ -z "$1" ]] || echo "http://host/$1.htm"
}
# Format your line (see printf help)
function print_row () {
printf "%-20s|%5s|%-30s|%s\n" "$@"
}
# The perl line reformat
perl -0777 -pe 's/([^"])\s*\n/\1 /g ; s/[",]//g' < sample.txt |
while read -r line ; do
arr=(${line})
print_row "${arr[0]}" "$((${#arr[@]} - 1))" "${arr[1]}" "$(get_vuln_url ${arr[1]})"
#echo -e "${arr[0]}\t|$vul_count\t|${arr[1]}\t|$(get_vuln_url ${arr[1]})"
for v in "${arr[@]:2}" ; do
print_row " " " " "$v" "$(get_vuln_url ${arr[1]})"
done
done
输出:
google.com | 3|vuln_example1 |http://host/vuln_example1.htm
| |vuln_example2 |http://host/vuln_example1.htm
| |vuln_example3 |http://host/vuln_example1.htm
facebook.com | 1|vuln_example2 |http://host/vuln_example2.htm
reddit.com | 1|stupidly_long_vuln_name1 |http://host/stupidly_long_vuln_name1.htm
stackoverflow.com | 0| |
更新。 如果您没有 Perl,并且您的文件没有表格,则可以使用此命令作为解决方法:
tr '\n' '\t' < sample.txt | sed -r -e 's/([^"])\s*\t/\1 /g' -e 's/[",]//g' -e 's/\t/\n/g'
tr '\n' '\t'
用表格替换所有行尾sed
part 的作用类似于 Perl 行,除了它处理制表符而不是行尾并将制表符恢复到行尾。
推荐阅读
- javascript - 有没有办法在javascript中的一行中将整个对象复制到类的属性中?
- python - 如何在python中解析动态json键
- php - 如何在数据库中插入多个选择下拉值,php codeigniter
- azure - 删除 Azure AD DS 的影响
- google-sheets - 如何解决“GTE 的数组参数大小不同”的错误?
- node.js - Nodejs 后端 API 在 dockerized 时需要更多时间来连接到 mongodb
- python - 在 Django ModelAdmin 中显示继承的字段
- azure-devops - 如何使用 TFVC 组织开发生命周期
- angular - TypeError: (options.astTransformers || []).map 不是函数 angular 10
- c# - ViewBag 没有向视图发送任何值