更新 Shell 中特定列的分隔符
Update Delimiter of Specific Columns in Shell
我有一个CSV文件,CSV文件的列数是10。但是有一列包含","这个值。我想将文件的分隔符更改为 "|" 而不更改包含 " 的列中的数据,"
我有文件
John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995
Bill Mark,19, Australia,3653,Main Street, People Two, Perth,Main Worker,20-05-1995
Mark Home,19,USA,3653, Redmond, Ground Town, Main Street, Virginia,Main Worker,20-05-1995
需要输出
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995
Bill Mark|19|Australia|3653|Main Street, People Two, Perth|Main Worker,20-05-1995
Mark Home|19|USA|3653| Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995
我尝试了多种解决方案,但无法实现我想要的。我尝试了以下命令,它只更新前 4 列的分隔符。
sed 's/,/|/;s/,/|/;s/,/|/;s/,/|/' file
我正在寻找的方法是更新前 4 列和后 2 列的分隔符。通过这种方式,我可以获得带有更新分隔符的文件,并且地址列对其没有影响。
使用 sed (GNU sed) 4.7 :
sed 's/, /\o0/g;s/,/|/g;s/\d0/, /g' file
您文件中的字段分隔符是逗号,但有些字段可以包含逗号。
正如您在数据中看到的那样,字段中的逗号永远不会单独出现。
幸运的是它后面总是有一个space。
所以首先,将 ', ' 转换为 char NUL (\o0)。这个字符永远不会出现在文本文件中。
之后,将所有逗号转换为'|'
最后,恢复 ', '
或者,对于 GNU Awk 5.1.0,API:3.0(GNU MPFR 4.1.0、GNU MP 6.2.1)
awk -F', ' 'BEGIN{OFS=FS}{for(i=1;i<=NF;i++)gsub(",","|",$i)}1' file
你可以使用awk。这种脚本可以完成工作:
t='John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995'
echo $t | awk '{ORS="";N=split([=10=],a,",");\
print a[1]"|"a[2]"|"a[3]"|"a[4]"|"; \
for(i=5;i<N-1;i++) print a[i];
print "|"a[N-1]"|"a[N] }'
从给出的简单示例来看,您要保留的逗号是唯一后跟 spaces 的逗号。
$: cat foo
Name,Age,Country,ID,Address,Category,DOB
John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995
Bill Mark,19, Australia,3653,Main Street, People Two, Perth,Main Worker,20-05-1995
Mark Home,19,USA,3653, Redmond, Ground Town, Main Street, Virginia,Main Worker,20-05-1995
$: sed -E 's/,(\S)/|/g' foo
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
Bill Mark|19, Australia|3653|Main Street, People Two, Perth|Main Worker|20-05-1995
Mark Home|19|USA|3653, Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995
这会扫描后跟 NONspace 的逗号,并记住后面的字符。
它将匹配的逗号(和下面保存的字符)替换为竖线(和下面保存的字符)。它将忽略后跟 space 的逗号,因为它们与模式不匹配。
这仍然适用于所有提供的示例。
对于逗号后没有 space 的情况,您将不得不重建该行。
$: cat foo
Name,Age,Country,ID,Address,Category,DOB
John Doe,19,England,3653,Manchester, England,Part Time Worker,20-05-1995
Bill Mark,19, Australia,3653,Main Street, People Two, Perth,Main Worker,20-05-1995
Mark Home,19,USA,3653, Redmond, Ground Town, Main Street, Virginia,Main Worker,20-05-1995
$: cat tst
while IFS=, read -a line; # read and split
do set -- "${line[@]}" # set as , etc
for i in 0 1 2 3; do printf "%s|" ""; shift; done; # print first 4
while (( 3 < $# )); do printf "%s, " ""; shift; done # all BUT last 3
printf "%s|" "" "" # last 2 get |
echo "" # last 1 gets \n
done<foo
$: ./tst
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995
Bill Mark|19| Australia|3653|Main Street, People Two, Perth|Main Worker|20- 05-1995
Mark Home|19|USA|3653| Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995
请注意,这样做会保留字段中的前导 space。如果你想删除那些你需要手动完成,但是你可以一次性完成整个文件:
sed -E 's/[|]\s+/\|/g' file
如果你真的想 trim 所有领域都 leading/trailing 白色 space -
sed -E 's/^\s+//; s/\s+[|]\s+/\|/g; s/\s+$//;' file
例如:
$: ./tst| sed -E 's/[|]\s+/\|/g'
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995
Bill Mark|19|Australia|3653|Main Street, People Two, Perth|Main Worker|20-05-1995
Mark Home|19|USA|3653|Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995
我有一个CSV文件,CSV文件的列数是10。但是有一列包含","这个值。我想将文件的分隔符更改为 "|" 而不更改包含 " 的列中的数据,"
我有文件
John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995
Bill Mark,19, Australia,3653,Main Street, People Two, Perth,Main Worker,20-05-1995
Mark Home,19,USA,3653, Redmond, Ground Town, Main Street, Virginia,Main Worker,20-05-1995
需要输出
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995
Bill Mark|19|Australia|3653|Main Street, People Two, Perth|Main Worker,20-05-1995
Mark Home|19|USA|3653| Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995
我尝试了多种解决方案,但无法实现我想要的。我尝试了以下命令,它只更新前 4 列的分隔符。
sed 's/,/|/;s/,/|/;s/,/|/;s/,/|/' file
我正在寻找的方法是更新前 4 列和后 2 列的分隔符。通过这种方式,我可以获得带有更新分隔符的文件,并且地址列对其没有影响。
使用 sed (GNU sed) 4.7 :
sed 's/, /\o0/g;s/,/|/g;s/\d0/, /g' file
您文件中的字段分隔符是逗号,但有些字段可以包含逗号。
正如您在数据中看到的那样,字段中的逗号永远不会单独出现。
幸运的是它后面总是有一个space。
所以首先,将 ', ' 转换为 char NUL (\o0)。这个字符永远不会出现在文本文件中。
之后,将所有逗号转换为'|'
最后,恢复 ', '
或者,对于 GNU Awk 5.1.0,API:3.0(GNU MPFR 4.1.0、GNU MP 6.2.1)
awk -F', ' 'BEGIN{OFS=FS}{for(i=1;i<=NF;i++)gsub(",","|",$i)}1' file
你可以使用awk。这种脚本可以完成工作:
t='John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995'
echo $t | awk '{ORS="";N=split([=10=],a,",");\
print a[1]"|"a[2]"|"a[3]"|"a[4]"|"; \
for(i=5;i<N-1;i++) print a[i];
print "|"a[N-1]"|"a[N] }'
从给出的简单示例来看,您要保留的逗号是唯一后跟 spaces 的逗号。
$: cat foo
Name,Age,Country,ID,Address,Category,DOB
John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995
Bill Mark,19, Australia,3653,Main Street, People Two, Perth,Main Worker,20-05-1995
Mark Home,19,USA,3653, Redmond, Ground Town, Main Street, Virginia,Main Worker,20-05-1995
$: sed -E 's/,(\S)/|/g' foo
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995
Bill Mark|19, Australia|3653|Main Street, People Two, Perth|Main Worker|20-05-1995
Mark Home|19|USA|3653, Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995
这会扫描后跟 NONspace 的逗号,并记住后面的字符。
它将匹配的逗号(和下面保存的字符)替换为竖线(和下面保存的字符)。它将忽略后跟 space 的逗号,因为它们与模式不匹配。
这仍然适用于所有提供的示例。
对于逗号后没有 space 的情况,您将不得不重建该行。
$: cat foo
Name,Age,Country,ID,Address,Category,DOB
John Doe,19,England,3653,Manchester, England,Part Time Worker,20-05-1995
Bill Mark,19, Australia,3653,Main Street, People Two, Perth,Main Worker,20-05-1995
Mark Home,19,USA,3653, Redmond, Ground Town, Main Street, Virginia,Main Worker,20-05-1995
$: cat tst
while IFS=, read -a line; # read and split
do set -- "${line[@]}" # set as , etc
for i in 0 1 2 3; do printf "%s|" ""; shift; done; # print first 4
while (( 3 < $# )); do printf "%s, " ""; shift; done # all BUT last 3
printf "%s|" "" "" # last 2 get |
echo "" # last 1 gets \n
done<foo
$: ./tst
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995
Bill Mark|19| Australia|3653|Main Street, People Two, Perth|Main Worker|20- 05-1995
Mark Home|19|USA|3653| Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995
请注意,这样做会保留字段中的前导 space。如果你想删除那些你需要手动完成,但是你可以一次性完成整个文件:
sed -E 's/[|]\s+/\|/g' file
如果你真的想 trim 所有领域都 leading/trailing 白色 space -
sed -E 's/^\s+//; s/\s+[|]\s+/\|/g; s/\s+$//;' file
例如:
$: ./tst| sed -E 's/[|]\s+/\|/g'
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995
Bill Mark|19|Australia|3653|Main Street, People Two, Perth|Main Worker|20-05-1995
Mark Home|19|USA|3653|Redmond, Ground Town, Main Street, Virginia|Main Worker|20-05-1995