Sed 在第二次出现时替换
Sed replace at second occurrence
我想用 sed 删除模式,仅在第二次出现时。这是我想要的,删除一个模式,但在第二次出现时。
file.csv 中的内容:
a,Name(null)abc.csv,c,d,Name(null)abc.csv,f
a,Name(null)acb.csv,c,d,Name(null)acb.csv,f
a,Name(null)cba.csv,c,d,Name(null)cba.csv,f
想要的输出:
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f
这是我试过的:
sed -r 's/(\(null)\).*csv//' file.csv
这里的问题是正则表达式太贪心了,但我无法停止。
我也试过这个,跳过第一次出现的 "null":
sed -r '0,/null/! s/(\(null)\).*csv//' file.csv
也试过了,但贪婪的正则表达式仍然是问题。
sed -r 's/(\(null)\).*csv//2' file.csv
我读到 ?
可以使正则表达式 "lazy",但我不能使它锻炼。
sed -r 's/(\(null)\).*?csv//' file.csv
更健壮的awk解决方案:
扩展示例文件 input.csv
:
12,Name(null)randomstuff.csv,2,3,Name(null)randomstuff.csv, false,Name(null)randomstuff.csv
12,Name(null)AotherRandomStuff.csv,2,3,Name(null)AotherRandomStuff.csv, false,Name(null)randomstuff.csv
12,Name(null)alphaNumRandom.csv,2,3,Name(null)alphaNumRandom.csv, false,Name(null)randomstuff.csv
工作:
awk -F, '{ c=0; for(i=1;i<=NF;i++) if($i~/\(null\)/ && c++==1) sub(/\(null\).*/,"",$i) }1' OFS=',' input.csv
输出:
12,Name(null)randomstuff.csv,2,3,Name, false,Name(null)randomstuff.csv
12,Name(null)AotherRandomStuff.csv,2,3,Name, false,Name(null)randomstuff.csv
12,Name(null)alphaNumRandom.csv,2,3,Name, false,Name(null)randomstuff.csv
sed
确实提供了一种简单的方法来指定要替换的匹配项。只需在分隔符后添加数字
$ sed 's/(null)[^.]*\.csv//2' ip.csv
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f
$ # or [^,] if there are no , within fields
$ sed 's/(null)[^,]*//2' ip.csv
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f
此外,在不使用扩展正则表达式时无需转义()
执行:
awk '{sub(/.null.....csv,f/,",f")}1' file
输出应该是:
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f
我想用 sed 删除模式,仅在第二次出现时。这是我想要的,删除一个模式,但在第二次出现时。
file.csv 中的内容:
a,Name(null)abc.csv,c,d,Name(null)abc.csv,f
a,Name(null)acb.csv,c,d,Name(null)acb.csv,f
a,Name(null)cba.csv,c,d,Name(null)cba.csv,f
想要的输出:
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f
这是我试过的:
sed -r 's/(\(null)\).*csv//' file.csv
这里的问题是正则表达式太贪心了,但我无法停止。 我也试过这个,跳过第一次出现的 "null":
sed -r '0,/null/! s/(\(null)\).*csv//' file.csv
也试过了,但贪婪的正则表达式仍然是问题。
sed -r 's/(\(null)\).*csv//2' file.csv
我读到 ?
可以使正则表达式 "lazy",但我不能使它锻炼。
sed -r 's/(\(null)\).*?csv//' file.csv
更健壮的awk解决方案:
扩展示例文件 input.csv
:
12,Name(null)randomstuff.csv,2,3,Name(null)randomstuff.csv, false,Name(null)randomstuff.csv
12,Name(null)AotherRandomStuff.csv,2,3,Name(null)AotherRandomStuff.csv, false,Name(null)randomstuff.csv
12,Name(null)alphaNumRandom.csv,2,3,Name(null)alphaNumRandom.csv, false,Name(null)randomstuff.csv
工作:
awk -F, '{ c=0; for(i=1;i<=NF;i++) if($i~/\(null\)/ && c++==1) sub(/\(null\).*/,"",$i) }1' OFS=',' input.csv
输出:
12,Name(null)randomstuff.csv,2,3,Name, false,Name(null)randomstuff.csv
12,Name(null)AotherRandomStuff.csv,2,3,Name, false,Name(null)randomstuff.csv
12,Name(null)alphaNumRandom.csv,2,3,Name, false,Name(null)randomstuff.csv
sed
确实提供了一种简单的方法来指定要替换的匹配项。只需在分隔符后添加数字
$ sed 's/(null)[^.]*\.csv//2' ip.csv
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f
$ # or [^,] if there are no , within fields
$ sed 's/(null)[^,]*//2' ip.csv
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f
此外,在不使用扩展正则表达式时无需转义()
执行:
awk '{sub(/.null.....csv,f/,",f")}1' file
输出应该是:
a,Name(null)abc.csv,c,d,Name,f
a,Name(null)acb.csv,c,d,Name,f
a,Name(null)cba.csv,c,d,Name,f