我有一个文件Builder.java
,其中包含以下行:
public class Builder{
@Override
public void setCallId(long value) {
set4ByteField(value, 48);
setLogtype(1);
setVerify("ABAB");
}
public void setOriginCallId(long value) {
set8ByteField(value, 52);
}
public void setDateTimeYear(int value) {
set2ByteField(value, 60);
}
...
然后我只想将> 50 的数字替换为数字+1,其他所有内容保持原样。结果:
public class Builder{
@Override
public void setCallId(long value) {
set4ByteField(value, 48);
setLogtype(1);
setVerifyflag("ABAB");
}
public void setOriginCallId(long value) {
set8ByteField(value, 53);
}
public void setDateTimeYear(int value) {
set2ByteField(value, 61);
}
....
}
我尽了最大努力,但编写了不起作用的脚本,例如:
cat Builder.java | awk -F'[,)]' '$2>50 {print $2+1}' > Builder.java
答案1
将绝对值大于 50 的所有数字递增。
perl -pe 's/\b(\d+)\b/$1>50 ? $1+1 : $1/ge' file
\d+
该模式是带有边界( )的数字序列( ),因此它与 中的\b
数字不匹配。4
set4ByteField
e
旗帜命令末尾允许将替换视为表达式,即 三元表达式于被俘集团。将所有大于 50 的数字递增。
perl -pe 's/(^|[^-])\b(\d+)\b/$1.($2>50 ? $2+1 : $2)/ge' file
^|[^-]
匹配行的开头或数字序列左侧除连字符减号之外的任何字符。这排除了负数。
顺便说一句,您不应该同时写入文件和读取文件。您尝试在处理文件之前截断该文件,因此您会得到一个空文件。要就地编辑文件,请使用 Perl 的-i
标志(请参阅
命令行选项)。更好的是,-i.bak
使用扩展名保存原始文件,.bak
以防出现问题。
答案2
你awk
几乎是对的,但你想交替一个字段,然后打印整行。此外,输出字段分隔符也被删除,并手动添加了缺少的逗号和右括号:
awk 'BEGIN {FS="[,)]" ; OFS="" } /ByteField/ && $2 > 50 {$2=", "$2+1")"} ; 1' file
如果1
始终为 true,则始终打印该行(对于所有行) - 请注意,它必须在更改字段后完成。我添加了一个匹配以/ByteField/
提高鲁棒性。
对于替换文件:cat
与输出具有相同文件的命令的冗余和管道将中断。使用其他方法。例如
使用 GNU awk
awk -i inplace 'BEGIN ....' file
带海绵
awk 'BEGIN ...' file | sponge file
或者借助临时文件
awk 'BEGIN ...' file > file.alt
mv file.alt file