用 awk 替换并保留 FS 到 OFS
Replacing with Awk and preserving the FS to OFS
我有一个文件,下面有输入文本(这不是原始文件,只是输入文本的示例),我想将所有 2 个字母的字符串替换为数字 100。在这个文件中 FS 可以是 :,|或 " " (space) ,我别无选择,只能将它们全部视为 FS,并且我想将这些字段分隔符保留在输出 [=13 中的原始位置(如输入文件中) =]
A:B C|D
AA:C EE G
BB|FF XX1 H
DD:MM:YY K
我试过了
awk -F"[:| ]" '{gsub(/[A-Z]{2}/,"100");print}'
但这好像不行,请指点。
期望的输出:
A:B C|D
100:C 1000 G
100|100 1001 H
100:100:100 K
在这种情况下
sed 's/[A-Z]\{2\}/100/g' YourFile
awk '{gsub(/[A-Z]{2}/, "100"); print}' YourFile
在这种情况下不需要字段分隔,将所有大写字母组更改为“100”,除非您在 OP 中指定其他约束(就像字符串中的其他元素一样,您需要指定可能的内容和理想情况下,将预期结果的样本添加为 univoq)
现在你肯定有更多的东西了,所以这段代码肯定会失败,因为把 ABC:DEF
和 100C:100F
之类的东西改成肯定不是预期的
在这种情况下
awk -F '[[:blank:]:|]+' '
{
split( [=11=], aS, /[^[:blank:]:|]+/)
for( i=1;i<=NF;i++){
if( $i ~ /^[A-Z][A-Z]$/) $i = "100"
printf( "%s%s", $i, aS[i+1])
}
printf( "\n" )
} ' YourFile
试试这个 sed one-liner:
kent$ sed -r 's/(^|[:| ])[A-Z][A-Z]([:| ]|$)/00/g' file
A:B C|D
100:C 100 G
100|FF XX1 H
100:MM:100 K
注:
这将搜索和替换模式:两个分隔符 之间的确切两个 [A-Z]。如果这不是您想要的,请粘贴所需的输出。
POSIX awk 没有保留与 RS (POSIX) 定义的字符串或 FS 定义的正则表达式相匹配的字符串的功能。由于在 POSIX 中 RS 只是一个字符串,因此不需要这样的功能,并且由于很少需要,所以对每个 FS 匹配字符串执行此操作将不必要地低效。
使用 GNU awk,其中 RS 可以是正则表达式,而不仅仅是字符串,您可以保留与正则表达式 RS 与 RT 匹配的字符串,但没有功能可以保留与 FS 匹配的值,原因与POSIX 不这样做。相反,在 GNU awk 中,他们向 split() 添加了第 4 个参数,因此如果需要,您可以自己在数组中保留与 FS 匹配的字符串(seps[]
下面):
$ awk -v FS='[:| ]' '{
split([=10=],flds,FS,seps)
gsub(/[A-Z]{2}/,"100")
for (i=1;i<=NF;i++) {
printf "%s%s", $i, seps[i]
}
print ""
}' file
A:B C|D
100:C 100 G
100|100 1001 H
100:100:100 K
在 the GNU awk manual 中查找 split()
了解更多信息。
你的代码似乎在我的 Gnu awk 上工作得很好:
A:B C|D
100:C 100 G # even the typo in this record got fixed.
100|100 1001 H
100:100:100 K
我会说问题是正则表达式 /[A-Z]{2}/
应该写成 /[A-Z][A-Z]/
.
我有一个文件,下面有输入文本(这不是原始文件,只是输入文本的示例),我想将所有 2 个字母的字符串替换为数字 100。在这个文件中 FS 可以是 :,|或 " " (space) ,我别无选择,只能将它们全部视为 FS,并且我想将这些字段分隔符保留在输出 [=13 中的原始位置(如输入文件中) =]
A:B C|D
AA:C EE G
BB|FF XX1 H
DD:MM:YY K
我试过了
awk -F"[:| ]" '{gsub(/[A-Z]{2}/,"100");print}'
但这好像不行,请指点。
期望的输出:
A:B C|D
100:C 1000 G
100|100 1001 H
100:100:100 K
在这种情况下
sed 's/[A-Z]\{2\}/100/g' YourFile
awk '{gsub(/[A-Z]{2}/, "100"); print}' YourFile
在这种情况下不需要字段分隔,将所有大写字母组更改为“100”,除非您在 OP 中指定其他约束(就像字符串中的其他元素一样,您需要指定可能的内容和理想情况下,将预期结果的样本添加为 univoq)
现在你肯定有更多的东西了,所以这段代码肯定会失败,因为把 ABC:DEF
和 100C:100F
之类的东西改成肯定不是预期的
在这种情况下
awk -F '[[:blank:]:|]+' '
{
split( [=11=], aS, /[^[:blank:]:|]+/)
for( i=1;i<=NF;i++){
if( $i ~ /^[A-Z][A-Z]$/) $i = "100"
printf( "%s%s", $i, aS[i+1])
}
printf( "\n" )
} ' YourFile
试试这个 sed one-liner:
kent$ sed -r 's/(^|[:| ])[A-Z][A-Z]([:| ]|$)/00/g' file
A:B C|D
100:C 100 G
100|FF XX1 H
100:MM:100 K
注:
这将搜索和替换模式:两个分隔符 之间的确切两个 [A-Z]。如果这不是您想要的,请粘贴所需的输出。
POSIX awk 没有保留与 RS (POSIX) 定义的字符串或 FS 定义的正则表达式相匹配的字符串的功能。由于在 POSIX 中 RS 只是一个字符串,因此不需要这样的功能,并且由于很少需要,所以对每个 FS 匹配字符串执行此操作将不必要地低效。
使用 GNU awk,其中 RS 可以是正则表达式,而不仅仅是字符串,您可以保留与正则表达式 RS 与 RT 匹配的字符串,但没有功能可以保留与 FS 匹配的值,原因与POSIX 不这样做。相反,在 GNU awk 中,他们向 split() 添加了第 4 个参数,因此如果需要,您可以自己在数组中保留与 FS 匹配的字符串(seps[]
下面):
$ awk -v FS='[:| ]' '{
split([=10=],flds,FS,seps)
gsub(/[A-Z]{2}/,"100")
for (i=1;i<=NF;i++) {
printf "%s%s", $i, seps[i]
}
print ""
}' file
A:B C|D
100:C 100 G
100|100 1001 H
100:100:100 K
在 the GNU awk manual 中查找 split()
了解更多信息。
你的代码似乎在我的 Gnu awk 上工作得很好:
A:B C|D
100:C 100 G # even the typo in this record got fixed.
100|100 1001 H
100:100:100 K
我会说问题是正则表达式 /[A-Z]{2}/
应该写成 /[A-Z][A-Z]/
.