【问题标题】:Parsing CSV file in bash script [duplicate]在 bash 脚本中解析 CSV 文件 [重复]
【发布时间】:2013-07-24 20:05:17
【问题描述】:

我正在尝试将包含典型访问控制矩阵表的 CSV 文件解析为 shell 脚本。我的示例 CSV 文件将是

"user","admin","security"  
"user1","x",""  
"user2","","x"  
"user3","x","x"

我将使用此列表在它们各自的文件夹中创建文件。问题是如何让它存储第 2/3 列(管理员/安全)的值?我试图实现的输出是对所有具有管理员/安全权限的用户进行分组/排序,并在各自的文件夹中创建文件。 (我的想法可能是将所有管理员/安全用户存储到不同的文件中并从那里运行。)

环境不允许我使用任何 Perl 或 Python 程序。但是任何awksed 命令都非常感谢。

我想要的输出是

$ cat sample.csv
“用户”、“管理员”、“安全”
"user1","x",""
"user2","","x"
"user3","x","x"
$ cat security.csv
用户2
用户3
$ cat admin.csv
用户1
用户3

【问题讨论】:

  • 不要将用户存储到文件中——他们可能会窒息。
  • 为什么标题行有5列?两个前导逗号是错误的吗?在文件正文中,除了"""x" 的格式,您是否必须处理任何替代?
  • 我在标题行的错误,将对其进行编辑。 csv 的格式只有 x 和空格
  • 这样更好。我想,我应该要求您显示所需的输出。然而,我认为Justin L. 在他的answer 覆盖了合理的基础方面做得不错。如果您的要求不能用它来解决,您需要显示您期望的输出来自给定的数据文件。

标签: bash csv sed awk


【解决方案1】:

如果你可以使用cut(1)(如果你使用任何类型的unix,你可能可以使用)你可以使用

cut -d , -f (n) (file)

n 是您想要的列。

您可以使用一系列列 (2-3) 或列列表 (1,3)。

这将留下引号,但您可以使用 sed 命令或其他轻量级的命令。

$ cat sample.csv
"user","admin","security"
"user1","x",""
"user2","","x"
"user3","x","x"

$ cut -d , -f 2 sample.csv
"admin"
"x"
""
"x"

$ cut -d , -f 3 sample.csv
"security"
""
"x"
"x"

$ cut -d , -f 2-3 sample.csv
"admin","security"
"x",""
"","x"
"x","x"

$ cut -d , -f 1,3 sample.csv
"user","security"
"user1",""
"user2","x"
"user3","x"

请注意,这不适用于一般的 csv 文件(不处理转义逗号),但它应该适用于类似于示例中简单用户名和 x 格式的文件。


如果您只想获取用户名列表,那么awk 几乎就是为这项工作而设计的工具,下面的答案做得很好,我不需要重复。

但 grep 解决方案可能更快更轻量级

grep 解决方案:

grep '^\([^,]\+,\)\{N\}"x"'

其中N 是第 N 列,用户是第 0 列。

$ grep '^\([^,]\+,\)\{1\}"x"' sample.csv
"user1","x",""
"user3","x","x"

$ grep '^\([^,]\+,\)\{2\}"x"' sample.csv
"user2","","x"
"user3","x","x"

从那里您可以使用cut 获取第一列:

$ grep '^\([^,]\+,\)\{1\}"x"' sample.csv | cut -d , -f 1
"user1"
"user3"

sed 's/"//g' 去掉引号:

$ grep '^\([^,]\+,\)\{1\}"x"' sample.csv | cut -d , -f 1 | sed 's/"//g'
user1
user3

$ grep '^\([^,]\+,\)\{2\}"x"' sample.csv | cut -d , -f 1 | sed 's/"//g'
user2
user3

【讨论】:

  • 当字段中有值时,有没有办法只抓取用户?期望的输出是列出所有拥有安全权限的用户
  • @user1358062 使用grep(1)cut(1)sed(1) 添加它:)
  • 非常感谢,这完美地回答了我的问题
  • 如何将结果存储在变量中(nvm 我想通了:我相信 ` 字符是在 bash 中将命令存储到变量时使用的字符)。再次编辑:为什么当我这样做时换行符消失了?
【解决方案2】:

帮助您入门(请注意,这不适用于嵌入逗号的 csv 文件,您必须使用 csv 解析器):

awk -F, '
NR>1 { 
  gsub(/["]/,"",$0); 
  if($2!="" && $3!="") 
    print $1 " has both privileges"; 
    print $1 > "file"
}' csv

【讨论】:

  • 第二个print 是否有缩进问题,或者是因为两个print 语句周围没有大括号?
  • 我想我错过了一个大括号。感谢您的编辑! :)
  • 简单有效,+1
猜你喜欢
  • 2010-12-06
  • 1970-01-01
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 2016-02-08
  • 2011-05-16
相关资源
最近更新 更多