我需要在匹配字符串的第 n 个位置(在本例中为第二个)添加一个字符。例如,在一个文件中,text.txt
我想在字符串之前添加一个 N,"
在包含的字符串中的 only之后添加一个 Nblah
文本.txt:
"1blah8","na","8blah4"
"2blah5","na","10blah4"
"5blah5","na","1blah234"
我想得到一个text2.txt:
"Ν1blah8","na","Ν8blah4"
"Ν2blah5","na","Ν10blah4"
"Ν5blah5","na","Ν1blah234"
我已经尝试过了sed 's/.*blah.*/N&/' text.txt > text2.txt
,但我只在每行第一个找到的字符串中得到了N
之前的内容。"
答案1
另一种方法:
$ sed 's/"\([^"]*blah[^"]*"\)/"N\1/g' test.txt
"N1blah8","na","N8blah4"
"N2blah5","na","N10blah4"
"N5blah5","na","1blah234
正则表达式正在查找 a "
,然后查找 0 个或多个非"
字符,后跟 a blah
,然后"
再查找 0 个或多个非字符。由于括号的原因,这是被捕获并且以后可以称为\1
.因此,该命令将用其自身 ( ) 替换匹配的模式,\1
但"N
附加一个。这就是为什么第一个"
在括号之外。/g
末尾的修饰符使其替换每行中的所有匹配字符串。
如果您的sed
版本支持它,您可以将其简化为:
sed -E 's/"([^"]*blah[^"]*")/"N\1/g'
答案2
要sed
重复替换一行中的所有匹配项,请g
在最后一个之后添加标志/
:
$ sed 's/[^"]*blah/N&/g' test.txt
该g
标志将导致“对于正则表达式的所有非重叠匹配,而不仅仅是第一个匹配”进行替换(引自我系统上的手册)。
我还稍微更改了正则表达式,以便匹配"
之前不存在的所有字符。blah
这样,替换将N
在第一个数字之前插入 ,就在 之后"
。
答案3
如果您想在第n
th 个字符(其中n
是任意值)之后插入,那么您应该避免sed
.对于这项工作有更好的工具(例如awk
或perl
等python
),例如awk
您可以使用一个变量在每个匹配字段中的第 th 字符之后n
插入:STRING
n
PATTERN
awk -vn=2 'BEGIN{FS=OFS=","}{for (i=1; i<=NF; i++){ if ($i ~ /PATTERN/){
h=substr($i,1,n);t=substr($i,n+1,length($i));$i=h "STRING" t}}};1' infile
这假设您的文件是一个简单的数据集文件(字段中没有嵌入逗号)。
答案4
CSV 解析和处理可能非常复杂。这是一个 perl oneliner,它将 N 放在第一列和第三列前面,与内容无关:
步骤1,去掉双引号:
@F = map { /"(.*)"/ } @F;
第2步,插入N
第一列和第三列
$F[0,2] =~ s/^/N/;
第 3 步,以 CSV 形式加入数组
printf qq("%s"\n), join q(","), @F
运行 perl:
perl -F, -ane '@F = map { /"(.*)"/ } @F; $F[0,2] =~ s/^/N/; printf qq("%s"\n), join q(","), @F' csvfile
编辑:避免 eval 表达式安全风险的新方法(谢谢 terdon)。