我有一个 csv,其中前几行如下所示
c("4288", "57534"),MIB1
c("2272", "2385"),FHIT
c("5550", "10531", "56239"),PREP
c("25809", "23669"),TTLL1
我想操纵变量的数量,以便括号中分组的所有内容都是一个变量。不幸的是,我的文档有多个条目,例如第 3 行,其中有多个逗号分隔括号内的值。
是否有一个 sed 表达式只能操作括号内的逗号?
预期的输出将是这样的:
c("4288" "57534"), MIB1
c("2272" "2385"),FHIT
c("5550" "10531" "56239"),PREP
c("25809" "23669"),TTLL1
干杯。
答案1
使用perl
not 来sed
获得更高级的正则表达式:
perl -pe 's/(?:\G[^,)]*|\([^,)]*)\K,(?=.*?\))//g' input.csv
c("4288" "57534"),MIB1
c("2272" "2385"),FHIT
c("5550" "10531" "56239"),PREP
c("25809" "23669"),TTLL1
这将删除括号内出现的所有逗号。
答案2
我已经回答过相同的解决方案这里,这也适用于您的问题,此处稍作修改:
sed -E ':loop s/(\([^)]*),([^)]*\))/\1\2/; t loop' infile
分解:
笔记:未转义(
或)
外部字符类[...]
用于分组匹配;字符类中转义的\(
or或将会匹配文字和;是否定匹配,因此匹配“\)
[...]
(
)
^
[^)]
任何单个字符,但不是)
”。
那么我们有:
(\([^)]*)
:第一组比赛,\1
指的是后面的裁判。
,
: 匹配单个逗号。
([^)]*\))
:第二组比赛,回溯\2
指的是。
考虑如下所示的一个示例行并解释该匹配的工作原理:
c(("4288", "57534", "somtoher")),d("f1", "f2", "f3"),MIB1
这(\([^)]*),([^)]*\))
将匹配:
从第一个左括号
(
后跟除 a 以外的任何内容,)
一直,
到最后一个右括号)
;因此,第一组比赛\1
将匹配(("4288", "57534",
上面示例行的部分内容;那么从最后一个
,
到第一个右括号之后到第一个右括号及其)
本身都将在第二组比赛中\2
;它将成为"somtoher")
上面示例行的一部分。在 的替换部分中
\1\2
,我们将两个匹配的组恢复回来,但在它们之间删除了逗号。:loop s///; t loop
;执行步骤 1 到 3,直到在 sed 循环中清除(
&之间的所有逗号(用作标签)。)
loop
第一次尝试时,我们的示例行将更改为:
c(("4288", "57534" "somtoher")),d("f1", "f2", "f3"),MIB1
第二次尝试将是:
c(("4288" "57534" "somtoher")),d("f1", "f2", "f3"),MIB1
第三次尝试将是:
c(("4288" "57534" "somtoher")),d("f1", "f2" "f3"),MIB1
等等。