使用 sed 在匹配字符串的第 n 个位置添加字符

使用 sed 在匹配字符串的第 n 个位置添加字符

我需要在匹配字符串的第 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

如果您想在第nth 个字符(其中n是任意值)之后插入,那么您应该避免sed.对于这项工作有更好的工具(例如awkperlpython),例如awk您可以使用一个变量在每个匹配字段中的第 th 字符之后n插入:STRINGnPATTERN

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)。

相关内容