Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash如何用引号将csv文件第一行的值(如果不存在)包装起来_Bash_Csv_If Statement_Quotations - Fatal编程技术网

Bash如何用引号将csv文件第一行的值(如果不存在)包装起来

Bash如何用引号将csv文件第一行的值(如果不存在)包装起来,bash,csv,if-statement,quotations,Bash,Csv,If Statement,Quotations,前几天我问如何用引号包装csv文件第一行的值。我得到的答复非常有效 $ cat file.csv word1,word2,word3,word4,word5 12345,12346,12347,12348,12349 要仅在第一行中的项目周围加引号,请执行以下操作: $ sed '1 { s/^/"/; s/,/","/g; s/$/"/ }' file.csv "word1","word2","word3","word4","word5" 12345,12346,1234

前几天我问如何用引号包装csv文件第一行的值。我得到的答复非常有效

$ cat file.csv  
word1,word2,word3,word4,word5  
12345,12346,12347,12348,12349  
要仅在第一行中的项目周围加引号,请执行以下操作:

$ sed '1 { s/^/"/; s/,/","/g; s/$/"/ }' file.csv  
"word1","word2","word3","word4","word5"  
12345,12346,12347,12348,12349 

我现在需要测试值周围是否存在引号,以消除重复引用值的可能性

更改每个替换以包括可选引号:

sed -E '1 { s/^"?/"/; s/"?,"?/","/g; s/"?$/"/ }' file.csv
我添加了
-E
以启用扩展模式,因此
被理解为“0或1匹配”


您还可以继续使用基本模式(无
-E
),并将每个
替换为
{0,1\}
(再次,0或1匹配)或
*
(匹配0或更多)。

由于行/列处理,此问题更适合awk而不是
sed

awk 'BEGIN{FS=OFS=","} NR==1 {
   for (i=1; i<=NF; i++) {gsub(/^"|"$/, "", $i); $i = "\"" $i "\""}
} 1' file

"word1","word2","word3","word4","word5"
12345,12346,12347,12348,12349
awk'BEGIN{FS=OFS=“,”}NR==1{

对于(i=1;i保留现有的sed命令,首先删除所有可能的双引号:

sed '1 { s/"//g; s/^/"/; s/,/","/g; s/$/"/ }' file.csv 

为了测试每个答案,我创建了三个文件:

文件.csv

word1,word2,word3,word4,word5  
12345,12346,12347,12348,12349 
"word1","word2","word3","word4","word5"  
12345,12346,12347,12348,12349
"word1",word2,word3,"word4",word5  
12345,12346,12347,12348,12349
file2.csv

word1,word2,word3,word4,word5  
12345,12346,12347,12348,12349 
"word1","word2","word3","word4","word5"  
12345,12346,12347,12348,12349
"word1",word2,word3,"word4",word5  
12345,12346,12347,12348,12349
file3.csv

word1,word2,word3,word4,word5  
12345,12346,12347,12348,12349 
"word1","word2","word3","word4","word5"  
12345,12346,12347,12348,12349
"word1",word2,word3,"word4",word5  
12345,12346,12347,12348,12349
然后我创建了一个bash脚本

#!/bin/bash  

sed -E '1 { s/^"?/"/; s/"?,"?/","/g; s/"?$/"/ }' file.csv > final.csv  
sed -E '1 { s/^"?/"/; s/"?,"?/","/g; s/"?$/"/ }' file2.csv > final2.csv  
sed -E '1 { s/^"?/"/; s/"?,"?/","/g; s/"?$/"/ }' file3.csv > final3.csv 
然后我看了最后的文件,第一行很完美

# cat final*.csv  

"word1","word2","word3","word4","word5"  
12345,12346,12347,12348,12349  
"word1","word2","word3","word4","word5"  
12345,12346,12347,12348,12349  
"word1","word2","word3","word4","word5"  
12345,12346,12347,12348,12349  

带有
sed
awk
的正则表达式可能会遇到一系列似乎永无止境的失败边缘情况。相反,利用csv库可以提供更强大的健壮性

我发现Python的库是最好的选择,因为它:

  • 除了Python本身之外,广泛可用,没有繁重的依赖关系
  • 对您使用的Python版本不特别敏感
  • 有助于嵌入shell脚本;以及
  • 非常紧凑(一个班轮就可以了!)
  • 因此,我的解决方案大致如下:

    QUOTE_CSV_PY='import sys; import csv; csv.writer(sys.stdout, quoting=csv.QUOTE_ALL).writerows(csv.reader(sys.stdin))'
    head -1 file.csv | python -c "$QUOTE_CSV_PY"; tail -n +2 file.csv
    
    要分解它:

    • QUOTE\u CSV\u PY
      是一个shell变量,包含Python one-liner命令
    • Python命令只需导入标准的
      sys
      csv
      模块。然后,它创建一个csv编写器,使用
      QUOTE\u ALL
      集将数据写入
      stdout
      ,以便所有字段都被引用。它被输入一个从
      stdin
      读取的csv读取器
    • head-1
      将第一行发送给python解释器进行处理
    • ;tail-n+2
      等待处理完成,然后从第二行开始转储每一行

    这很接近。如果这些值已经有引号,除了最后一个值在引号前有空格外,其他值都保持不变,如:
    “word1”、“word2”、“word3”、“word4”、“word5”
    这一个非常有效。我甚至将引号放在随机值中,如:
    word1、word2、“word3”、“word4”、“word5”
    最终输出总是
    “word1”、“word2”、“word3”、“word4”、“word5”
    Tom此命令最适合我。如果值缺少引号,并且其中一些值有引号,则跳过它们,因此第一行如
    word1、“word2”、“word3”、“word4”,word5
    word1,word2,word3,word4,word5
    总是变成
    “word1”,“word2”,“word3”,“word4”,“word5”
    。你们帮了大忙。我当然非常感谢所有的帮助!唉,如果引用的字段有逗号,这就失败了。例如
    1,“2,2”,3
    变成
    “1”,“2”,“2”,“2”,“3”
    。你说得对,@Heath,可能还有许多其他输入会导致它失败,毕竟这只是一系列不了解上下文的替换。处理CSV文件的最佳方法是使用支持它们的工具,例如Python及其.fully,使用Python的
    CSV
    模块(在shell脚本中)这确实是我最后要做的。我会添加我的答案。很好,我唯一要说的是,
    “$QUOTE\u CSV\u PY”
    在使用它时应该被引用(它在这里没有令人讨厌的副作用,但可以与其他脚本一起使用)。完全正确。我在转录时错误地删除了引号。修复。