使用 awk 更改文件中第 n 行的第 n 个字符
Using awk to make changes to nth character in nth line in a file
我写了一个awk命令
awk 'NR==5 {sub(substr(,14,1),(substr(,14,1) + 1)); print "test.py"}' > test.py
这试图更改 python 文件第 5 行的第 14 个字符。由于某种原因,这不会停止执行,我必须打破它。它还会删除文件的内容。
示例输入:
import tools
tools.setup(
name='test',
tagvisc='0.0.8',
packages=tools.ges(),
line xyz
)
`
输出:
import tools
tools.setup(
name='test',
tagvisc='0.0.9',
packages=tools.ges(),
line xyz
)
远离固定的行号(NR==5
)和固定的字符位置(14
),而是动态地寻找你想要的change/increment,例如:
$ cat test.py
import tools
tools.setup(
name='test',
tagvisc='0.0.10',
packages=tools.ges(),
line xyz
)
一个 awk
增加 10
的想法(第 3 行,行中的第 3 个数字字符串):
awk '
/tagvisc=/ { split([=11=],arr,".") # split line on periods
sub("." arr[3]+0 "7","." arr[3]+1 "7") # replace .<oldvalue>7 with .<newvalue>7; 7 == single quote
}
1
' test.py
备注:
arr[3]
= 10',
; with arr[3]+0
awk
将获取最左边的全数字内容,去掉所有其他内容,然后添加 0
,留下 arr[3]
= 10
;同样的逻辑适用于 arr[3]+1
(arr[3]+1
= 11
);基本上是丢弃任何非数字后缀的技巧
- 如果文件中有多行字符串
tagvisc='x.y.z'
那么这将在所有行中更改 z
;我们可以通过添加更多逻辑来仅更改 first
的出现来解决这个问题,但我暂时不考虑它,假设这不是问题
这会生成:
import tools
tools.setup(
name='test',
tagvisc='0.0.11',
packages=tools.ges(),
line xyz
)
如果 objective 是用新值覆盖原始文件,您有几个选择:
# use temporary file:
awk '...' test.py > tmp ; mv tmp test.py
# if using GNU awk, and once accuracy of script has been verified:
awk -i inplace '...' test.py
像这样...
$ awk 'function join(a,k,s,sep) {for(k in a) {s=s sep a[k]; sep="."} return s}
BEGIN {FS=OFS="\""}
/^tagvisc=/{v[split(,v,".")]++; =join(v)}1' file > newfile
如果我理解您现在需要做的事情的细微差别,您需要使用 "."
作为 fieldsep 将第 5 条记录的第一个字段拆分为一个数组,然后删除 "\","
从数组的第三个元素的末尾开始(可选),然后递增数字并将字段放回原处。您可以这样做:
awk '{split(,a,"."); sub(/["],/,"",a[3]); =a[1]"."a[2]"."(a[3]+1)"\","}1'
(NR==5
省略举例)
例子Use/Output
$ echo 'tagvisc="3.4.30"', |
awk '{split(,a,"."); sub(/["],/,"",a[3]); =a[1]"."a[2]"."(a[3]+1)"\","}1'
tagvisc="3.4.31",
我将重定向到一个临时文件,然后返回到原始文件。如果这不是您需要的,请告诉我。
加上NR == 5
你会得到
awk 'NR==5 {split(,a,"."); sub(/["],/,"",a[3]); =a[1]"."a[2]"."(a[3]+1)"\","}1' test.py > tmp; mv -f tmp test.py
对第三个参数使用 GNU awk 来匹配 () 和“就地”编辑:
$ awk -i inplace '
match([=10=],/^([[:space:]]*tagvisc=7)([^7]+)(.*)/,a) {
split(a[2],ver,".")
[=10=] = a[1] ver[1] "." ver[2] "." ver[3]+1 a[3]
}
{ print }
' test.py
$ cat test.py
import tools
tools.setup(
name='test',
tagvisc='0.0.9',
packages=tools.ges(),
line xyz
)
使用 awk 更改文件中[mth]行的第 n 个字符:
$ awk 'BEGIN{FS=OFS=""}NR==5{=9}1' file # > tmp && mv tmp file
输出:
import tools
tools.setup(
name='test',
tagvisc='0.0.9', <----- this is not output but points to what changed
packages=tools.ges(),
line xyz
)
解释:
$ awk '
BEGIN {
FS=OFS="" # set the field separators to empty and you can reference
} # each char in record by a number
NR==5 { # 5th record
=9 # and 18th char is replaced with a 9
}1' file # > tmp && mv tmp file # output to a tmp file and replace
注意: 如果您尝试用单字节字符替换多字节字符(例如 utf8 ä
(0xc3 0xa4) 与 a
(0x61) 将导致 0x61 0xa4)。当然,在您要替换的位置之前的 ä
会使您的计算减去 1。
哦,是的,您可以用多个字符替换一个字符,但反之则不行。
我写了一个awk命令
awk 'NR==5 {sub(substr(,14,1),(substr(,14,1) + 1)); print "test.py"}' > test.py
这试图更改 python 文件第 5 行的第 14 个字符。由于某种原因,这不会停止执行,我必须打破它。它还会删除文件的内容。
示例输入:
import tools
tools.setup(
name='test',
tagvisc='0.0.8',
packages=tools.ges(),
line xyz
)
`
输出:
import tools
tools.setup(
name='test',
tagvisc='0.0.9',
packages=tools.ges(),
line xyz
)
远离固定的行号(NR==5
)和固定的字符位置(14
),而是动态地寻找你想要的change/increment,例如:
$ cat test.py
import tools
tools.setup(
name='test',
tagvisc='0.0.10',
packages=tools.ges(),
line xyz
)
一个 awk
增加 10
的想法(第 3 行,行中的第 3 个数字字符串):
awk '
/tagvisc=/ { split([=11=],arr,".") # split line on periods
sub("." arr[3]+0 "7","." arr[3]+1 "7") # replace .<oldvalue>7 with .<newvalue>7; 7 == single quote
}
1
' test.py
备注:
arr[3]
=10',
; witharr[3]+0
awk
将获取最左边的全数字内容,去掉所有其他内容,然后添加0
,留下arr[3]
=10
;同样的逻辑适用于arr[3]+1
(arr[3]+1
=11
);基本上是丢弃任何非数字后缀的技巧- 如果文件中有多行字符串
tagvisc='x.y.z'
那么这将在所有行中更改z
;我们可以通过添加更多逻辑来仅更改first
的出现来解决这个问题,但我暂时不考虑它,假设这不是问题
这会生成:
import tools
tools.setup(
name='test',
tagvisc='0.0.11',
packages=tools.ges(),
line xyz
)
如果 objective 是用新值覆盖原始文件,您有几个选择:
# use temporary file:
awk '...' test.py > tmp ; mv tmp test.py
# if using GNU awk, and once accuracy of script has been verified:
awk -i inplace '...' test.py
像这样...
$ awk 'function join(a,k,s,sep) {for(k in a) {s=s sep a[k]; sep="."} return s}
BEGIN {FS=OFS="\""}
/^tagvisc=/{v[split(,v,".")]++; =join(v)}1' file > newfile
如果我理解您现在需要做的事情的细微差别,您需要使用 "."
作为 fieldsep 将第 5 条记录的第一个字段拆分为一个数组,然后删除 "\","
从数组的第三个元素的末尾开始(可选),然后递增数字并将字段放回原处。您可以这样做:
awk '{split(,a,"."); sub(/["],/,"",a[3]); =a[1]"."a[2]"."(a[3]+1)"\","}1'
(NR==5
省略举例)
例子Use/Output
$ echo 'tagvisc="3.4.30"', |
awk '{split(,a,"."); sub(/["],/,"",a[3]); =a[1]"."a[2]"."(a[3]+1)"\","}1'
tagvisc="3.4.31",
我将重定向到一个临时文件,然后返回到原始文件。如果这不是您需要的,请告诉我。
加上NR == 5
你会得到
awk 'NR==5 {split(,a,"."); sub(/["],/,"",a[3]); =a[1]"."a[2]"."(a[3]+1)"\","}1' test.py > tmp; mv -f tmp test.py
对第三个参数使用 GNU awk 来匹配 () 和“就地”编辑:
$ awk -i inplace '
match([=10=],/^([[:space:]]*tagvisc=7)([^7]+)(.*)/,a) {
split(a[2],ver,".")
[=10=] = a[1] ver[1] "." ver[2] "." ver[3]+1 a[3]
}
{ print }
' test.py
$ cat test.py
import tools
tools.setup(
name='test',
tagvisc='0.0.9',
packages=tools.ges(),
line xyz
)
使用 awk 更改文件中[mth]行的第 n 个字符:
$ awk 'BEGIN{FS=OFS=""}NR==5{=9}1' file # > tmp && mv tmp file
输出:
import tools
tools.setup(
name='test',
tagvisc='0.0.9', <----- this is not output but points to what changed
packages=tools.ges(),
line xyz
)
解释:
$ awk '
BEGIN {
FS=OFS="" # set the field separators to empty and you can reference
} # each char in record by a number
NR==5 { # 5th record
=9 # and 18th char is replaced with a 9
}1' file # > tmp && mv tmp file # output to a tmp file and replace
注意: 如果您尝试用单字节字符替换多字节字符(例如 utf8 ä
(0xc3 0xa4) 与 a
(0x61) 将导致 0x61 0xa4)。当然,在您要替换的位置之前的 ä
会使您的计算减去 1。
哦,是的,您可以用多个字符替换一个字符,但反之则不行。