我在 Linux 机器上有这个输入文件,其中有多行:
123, 'John, Nesh', 731, 'ABC, DEV, 23', 6, 400 'Text'
123, 'John, Brown', 140, 'ABC, DEV, 23', 6, 500 'Some other, Text'
123, 'John, Amazing', 1, 'ABC, DEV, 23', 8, 700 'Another, example, Text'
等等。我想删除,
在单引号字段中找到的任何内容。预期输出:
123, 'John Nesh', 731, 'ABC DEV 23', 6, 400 'Text'
123, 'John Brown', 140, 'ABC DEV, 23', 6, 500 'Some other Text'
123, 'John Amazing', 1, 'ABC DEV, 23', 8, 700 'Another example, Text'
答案1
bash 5.2 有一个新的可加载模块,dsv
用于解析“分隔符分隔”值:
$ echo $BASH_VERSION
5.2.0(2)-release
$ cat input.csv
'123','ABC, DEV 23','345','534.202','NAME'
$ enable dsv
$ dsv -S -p -a fields "$(head -1 input.csv)"
$ declare -p fields
declare -a fields=([0]="'123'" [1]="'ABC, DEV 23'" [2]="'345'" [3]="'534.202'" [4]="'NAME'")
$ fields=( "${fields[@]//,/}" ) # remove commas from all elements
$ (IFS=,; echo "${fields[*]}")
'123','ABC DEV 23','345','534.202','NAME'
命令的帮助文本dsv
:
dsv: dsv [-a ARRAYNAME] [-d DELIMS] [-Sgp] 字符串
从 STRING 中读取分隔符分隔的字段。
将 STRING(一行分隔符分隔的值)解析为各个字段,并将它们存储到从索引 0 开始的索引数组 ARRAYNAME 中。解析会理解并跳过双引号字符串。如果未提供 ARRAYNAME,则“DSV”是默认数组名称。如果分隔符是逗号(默认情况下),则会按照 RFC 4180 中的指定解析逗号分隔的值。
-d 选项指定分隔符。分隔符是 DELIMS 参数的第一个字符。不支持指定包含多个字符的 DELIMS 参数,并且会产生意外结果。 -S 选项启用类似 shell 的引用:双引号字符串可以在特殊字符前面包含反斜杠,反斜杠将被删除;单引号字符串的处理方式与 shell 处理它们的方式相同。 -g 选项启用贪婪分割:在 STRING 的开头和结尾处跳过分隔符序列,并且 STRING 中分隔符的连续实例不会生成空字段。如果提供了 -p 选项,dsv 会将引号字符保留为生成字段的一部分;否则它们将被删除。
返回值为 0,除非提供了无效选项或者 ARRAYNAME 参数无效或只读。
答案2
和perl
:
perl -pe "s{'.*?'}{\$& =~ s/,//gr}ge" < your-file
'
它假设带引号的字符串永远不会跨越多行,并且带引号的字符串中没有转义的s '...'
(尽管如果它们像 csv 中常见的那样被转义,它仍然可以工作''
)。