我正在做我的课程完成工作,我需要操作一个有六十万行的 .csv 文件的一些列。我已经在几个论坛中搜索过关于 sed 和 awk 的内容,但没有找到类似的东西(不幸的是我对 Linux 的了解不是很深)。我发现通常只处理一列或全部......我需要的是仅在第一、第五和第六列中添加双引号。
例如:
2018-03-18 4:56:17,255.255.255.255,00,ssh,admin,123
成为
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
不过,也许我仍然会改变一些专栏,因为我刚刚开始数据挖掘,我不知道几周后配置会是什么样子,所以如果你能做一个简短的逻辑语法,我将永远感激不已。
答案1
使用csvtool
其中有一个有用的format
命令:
csvtool format '"%1",%2,%3,%4,"%5","%6"\n' file.csv
例子:
echo "2018-03-18 4:56:17,255.255.255.255,00,ssh,admin,123" |
csvtool format '"%1",%2,%3,%4,"%5","%6"\n' -
输出:
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
csvtool
还可以call
shell 函数和外部程序来解析行.CSV文件。使用 执行相同的操作printf
,但打印“123" 以十六进制形式执行:
echo "2018-03-18 4:56:17,255.255.255.255,00,ssh,admin,123" |
csvtool call "printf '\"%s\",%s,%s,%s,\"%s\",\"%x\"\n'" -
输出:
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","7b"
答案2
我可以这样用 awk 来处理它:
- 将输出字段分隔符设置为输入字段分隔符,我们将其指定为逗号
-F,
- 对于每一行,将字段 1、5 和 6 的值重新分配为原始值,但用双引号引起来。明显的引用混乱是因为我使用双引号来创建周围的字符串,并且因为我想要打印的唯一字符串是双引号,我必须转义它,所以我想要的每个双引号最终都是
"\""
. - 更新字段后,打印新组合的字符串。
脚本是:
awk -F, 'BEGIN{ OFS=FS } {$1="\""$1"\""; $5="\""$5"\""; $6="\""$6"\""; print }' < input.csv > output.csv
当您发现需要引用更多字段时,只需执行与上面字段 1、5 和 6 相同的操作即可。
答案3
和perl
$ perl -F, -lane 'map {$_=qq("$_")} @F[0,4,5]; print join ",", @F' ip.txt
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
-F,
用作,
输入字段分隔符,结果在@F
数组中可用map {$_=qq("$_")} @F[0,4,5]
双引号需要数组元素。索引从 开始0
。这里使用运算符qq
是为了避免转义双引号,qq("$_")
与"\"$_\""
print join ",", @F
打印修改后的数组,
作为分隔符
另一种方法awk
$ awk -v q='"' 'BEGIN{split("1 5 6",a); FS=OFS=","}
{for(i in a) $a[i]=q $a[i] q} 1' ip.txt
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
-v q='"'
将双引号保存为q
变量中的值split("1 5 6",a)
将要更改的索引保存为a
数组中的值(默认按空格分割,FS 尚未更改)FS=OFS=","
将输入/输出分隔符更改为,
for(i in a) $a[i]=q $a[i] q
更改必填字段1
打印内容的惯用方式$0
答案4
有一个简单的方法:当您将 " 放在列的前面和末尾时,使用转义字符 \。
cat test.txt | awk '{ print $1" ""\""$2"\""}'
试一试。