我想生成一个 csv 文件来告诉哪些服务器具有特定的文件和所有权。这是我得到的原始输出:
server01,server02,server03,owner,/etc/file1
server04,owner,/etc/file2
server05,server06,owner,/etc/file3
我想用 Windows 格式换行 (CF+LR) 替换服务器名称之间的逗号,并在它们之间添加引号,以便 CSV 将在同一个框中显示所有服务器。
期望的输出:
"server01
server02
server03",owner,/etc/file1
"server04",owner,/etc/file2
"server05
server06",owner,/etc/file3
如何用sed实现?
,owner,
如果它是您想要包装在一个字段中的文字的所有内容:使用 GNU
sed
:与
perl
:如果它是除了最后两个字段之外的所有内容:
使用 GNU
sed
:与
perl
:或者使用
Text::CSV
perl 模块正确地进行 CSV 解析和格式化:如果文件以带 BOM 的 UTF-16 或 UTF-8 编码,这对于 Microsoft 文件来说并非闻所未闻,您可能必须适应(请参阅该方法),或者您可能更愿意以某种方式重新
perldoc Text::CSV
格式化<file dos2unix | ... | unix2dos
所以你可以处理理智的输入。我不会使用 来执行此操作
sed
,而是使用perl
(或者也许awk
- 但我必须编写自己的pop()
和join()
函数而不是使用 perl 内置函数):首先,它从数组中删除最后两个元素(所有者和文件名)
@F
(@F
为每个输入行自动创建,因为-a
选项使用逗号作为-F,
选项指定的字段分隔符 - 类似于 awk 自动拆分其输入的方式)和将它们存储在变量$file
和中$owner
。"\"" . join("\r\n", @F) . "\""
构造一个字符串,其中@F 的每个元素由 CR+LF 字符分隔,并且整个字符串用双引号引起来。$owner
这个字符串用and连接(用逗号)$file
,然后打印出来。您希望将第一个逗号分隔字段与所有以下字段组合起来,直到(但不包括)每条记录中的最后两个字段,通过引用它们,生成一个单引号 CSV 字段。然后您想要用 CR+LF 替换该组合字段中的嵌入逗号。
您可以通过反转文件中每一行的内容,在第二个逗号后插入双引号,再次反转该行并在开头插入双引号来轻松地做到这一点:
由于我们现在有一个正确引用的无头 CSV 文件,我们可以使用Miller(一种专门用于处理 CSV 等结构化数据的
mlr
工具)将第一个字段中的所有逗号替换为 CR+LF:请注意,不需要引用字段,因为在 Unix 系统上,字段和记录分隔符未嵌入此数据集中的字段中。我们可以通过单独调用从每条记录中提取第二个字段来显示这一点
mlr
:你想保留最后一个
sed
命令输出中的原始引用,然后使用--quote-original
:不过,理想情况下,您应该更正生成此损坏的 CSV 输出的任何代码,以便该字段从一开始就是正确的,而不是在后处理步骤中修复它。
仅使用米勒:
这会将文件读取为一个简单的逗号分隔、隐式索引的文本文件。然后它将第二个和后面的字段附加到第一个字段的末尾,以 CR+LF 作为分隔符,删除每个附加的字段,直到只剩下三个字段。然后它明确引用第一个字段。