替换 |管道分隔文件中具有值的记录之间的字符
Replace | character between the records with a value in a pipe delimited file
这是我的文件。
NAME|NUM|ADDR|AGE
abcd|02|abc|cd|12
jake|04|xy|zzb|12
lau|92||xcx| 56
我想要的输出必须是这样的
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|18
lau|92|#xcx| 56
我的文件有 4 个字段,第 3 个列在 "ice|cream" 等字符之间有一个竖线分隔符,我的要求是替换 |第三个字段具有任何值,如(#,*或任何)。由于这是管道分隔文件,我无法替换文件的特定部分 exclusively.Any 帮助对我来说非常有用..谢谢
awk 解决办法:
awk -F'|' 'NR==1;NR>1 && NF>4{ print ,,"#", }' OFS='|' file
NR==1;
- 按原样打印第一条记录
NR>1 && NF>4
- 检查记录是否有过多字段
"#"
- 内爆第 3 和第 4 个字段用新字符替换分隔符 #
输出:
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
lau|92|#xcx| 56
或者,如果您想要一个更传统的基于逻辑的解决方案,(而且公认的长手很痛苦;-/)这是另一个解决方案
awk -F\| 'BEGIN{OFS="|"}
{
#dbg print "#dbg:NF="NF;
# if this record has an extra character
if (NF>4){
# loop over all fields
for(i=1;i<=NF;i++){
# if not the field of interest or last field on line, just print it
if(i!=3 && i!=NF){
printf("%s|",$i)
}
# else this is the problem field, add the # char
else if (i==3){
printf "#"
}
# else if last field on line, add LF char at end
else if (i==NF){
printf ("%s\n",$i)
}
}
}
# record has correct number of FS chars
else {
print [=10=]
}
}' dat.txt
输出
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
lau|92|#xcx| 56
我已经在代码中添加了注释来解释发生了什么。
这里是最重要的一行;->
awk -F\| '{if (NF>4){for(i=1;i<=NF;i++){if(i!=3 && i!=NF){printf("%s|",$i)}else if(i==3){printf "#"}else if(i==NF){printf ("%s\n",$i)}}}else{print [=12=]}}' dat.txt
IHTH
只需将 n
设置为您要与其后的字段合并的字段的编号:
$ cat tst.awk
BEGIN { FS=OFS="|" }
NR==1 { print; next }
{
for (i=1;i<=NF;i++) {
sep = (i==n ? "#" : OFS)
printf "%s%s", $i, (i<NF ? sep : ORS)
}
}
$ awk -v n=3 -f tst.awk file
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
lau|92|#xcx| 56
$ awk -v n=2 -f tst.awk file
NAME|NUM|ADDR|AGE
abcd|02#abc|cd|12
jake|04#xy|zzb|12
lau|92#|xcx| 56
这是我的文件。
NAME|NUM|ADDR|AGE
abcd|02|abc|cd|12
jake|04|xy|zzb|12
lau|92||xcx| 56
我想要的输出必须是这样的
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|18
lau|92|#xcx| 56
我的文件有 4 个字段,第 3 个列在 "ice|cream" 等字符之间有一个竖线分隔符,我的要求是替换 |第三个字段具有任何值,如(#,*或任何)。由于这是管道分隔文件,我无法替换文件的特定部分 exclusively.Any 帮助对我来说非常有用..谢谢
awk 解决办法:
awk -F'|' 'NR==1;NR>1 && NF>4{ print ,,"#", }' OFS='|' file
NR==1;
- 按原样打印第一条记录NR>1 && NF>4
- 检查记录是否有过多字段"#"
- 内爆第 3 和第 4 个字段用新字符替换分隔符#
输出:
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
lau|92|#xcx| 56
或者,如果您想要一个更传统的基于逻辑的解决方案,(而且公认的长手很痛苦;-/)这是另一个解决方案
awk -F\| 'BEGIN{OFS="|"}
{
#dbg print "#dbg:NF="NF;
# if this record has an extra character
if (NF>4){
# loop over all fields
for(i=1;i<=NF;i++){
# if not the field of interest or last field on line, just print it
if(i!=3 && i!=NF){
printf("%s|",$i)
}
# else this is the problem field, add the # char
else if (i==3){
printf "#"
}
# else if last field on line, add LF char at end
else if (i==NF){
printf ("%s\n",$i)
}
}
}
# record has correct number of FS chars
else {
print [=10=]
}
}' dat.txt
输出
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
lau|92|#xcx| 56
我已经在代码中添加了注释来解释发生了什么。
这里是最重要的一行;->
awk -F\| '{if (NF>4){for(i=1;i<=NF;i++){if(i!=3 && i!=NF){printf("%s|",$i)}else if(i==3){printf "#"}else if(i==NF){printf ("%s\n",$i)}}}else{print [=12=]}}' dat.txt
IHTH
只需将 n
设置为您要与其后的字段合并的字段的编号:
$ cat tst.awk
BEGIN { FS=OFS="|" }
NR==1 { print; next }
{
for (i=1;i<=NF;i++) {
sep = (i==n ? "#" : OFS)
printf "%s%s", $i, (i<NF ? sep : ORS)
}
}
$ awk -v n=3 -f tst.awk file
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
lau|92|#xcx| 56
$ awk -v n=2 -f tst.awk file
NAME|NUM|ADDR|AGE
abcd|02#abc|cd|12
jake|04#xy|zzb|12
lau|92#|xcx| 56