从 stdout 修改字符串中的数值
Modify numeric values in strings from stdout
我有要重写和修改一些数值的输入字符串:
输入:src/main.tsx(2,31): error TS2304: Cannot find name 'foo'.
期望输出:src/main.tsx:1:30: error: TS2304: Cannot find name 'foo'.
注意:
- 数值减1了。
error
是动态的。也可以是warning
.
- 该命令会将输入通过管道传递给它 (
tsc | MAGIC_HAPPENS_HERE
)。如果有错误,那么这个命令应该传递错误。
到目前为止,我有以下内容:
sed -E "s/^([^(]+)\(([0-9]+),([0-9]+)\): ((warning)|(error)) (.*)/::: : /"
除数字操作外,此方法有效。根据我的阅读,我认为 sed
不是完成这项工作的正确工具。我查看了 awk
但遇到了正则表达式捕获组的问题。
我正在使用 MacOS。该命令不需要是可移植的。我很高兴使用 brew
.
安装其他工具
能否请您尝试以下。
awk '
match([=10=],/\([^)]*/){
value=substr([=10=],RSTART+1,RLENGTH-1)
num=split(value,array,",")
for(i=1;i<=num;i++){
val=(val?val":":"")array[i]-1
}
part_2=substr([=10=],RSTART+RLENGTH+1)
sub(/error/,"error:",part_2)
print substr([=10=],1,RSTART-1) ":" val part_2
value=part_2=""
}' Input_file
输出如下。
src/main.tsx:1:30: error TS2304: Cannot find name 'foo'.
说明:为以上代码添加详细说明。
awk ' ##Starting awk program here.
match([=12=],/\([^)]*/){ ##Using match function to match regex from ( till ) in line.
value=substr([=12=],RSTART+1,RLENGTH-1) ##Creating variable value which has value of sub-string from RSTART+1 to RLENGTH-1.
num=split(value,array,",") ##Using split, to split the value into an array named array.
for(i=1;i<=num;i++){ ##Running for loop from i=1 to till value of num(which is length of array).
val=(val?val":":"")array[i]-1 ##Creating variable val whose value is subtraction of array[i] value with 1 and keep concatenating to its own value.
}
part_2=substr([=12=],RSTART+RLENGTH+1) ##Creating variable part_2 whose value is rest of line after matched regex.
sub(/error/,"error:",part_2) ##Substituting string error with error: here in rest of the line.
print substr([=12=],1,RSTART-1) ":" val part_2 ##Printing sub-string from 1 to till match found, :, val and part_2 variables here.
value=part_2="" ##Nullify variables value and part_2 here.
}' Input_file ##Mentioning Input_file name here.
我同意 sed
不是合适的工具。由于过时(或者可能只是过时),我会使用 Perl:
$ cat data
src/main.tsx(2,31): error TS2304: Cannot find name 'foo'.
$ perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", , -1, -1, )/e' data
src/main.tsx:1:30: error: TS2304: Cannot find name 'foo'.
$
正则表达式延迟匹配所有内容,直到“(nn,mmm):
”后跟 'word',捕获两个数字以及括号和单词之前的内容。然后,它使用 /e
修饰符('evaluate the right side as an expression' — 请参阅 Regexp Quote-Like Operators)使用 sprintf()
进行减法以格式化信息。 'word' 将捕获 error
或 warning
或任何其他所有字母后跟空格的内容。您可以使用 \S+
代替 \w+
来捕获任何非 space 字符序列。我假设分隔符是单个空格;如果需要,您可以使用 \s+
代替空格,以匹配任何非空的白色序列 space。 (-p
选项仅表示“从命名文件或标准输入中读取行,如果没有命名文件,执行 -e '…script…'
中的操作并打印结果。)
已使用 5.18.4(/usr/bin/perl
在 macOS Mojave 10.14.6 上)和 5.30.0 进行测试。
如果您有一个产生错误的进程,那么您需要确保将错误发送到 Perl 脚本 — 那是 shell 脚本而不是其他任何东西。
tsc 2>&1 |
perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", , -1, -1, )/e'
如果您需要将命令的标准输出(修改后的问题中的tsc
和上面的shell脚本片段)转到其他地方,那么您需要小心(另请参见How to pipe stderr and not stdout),但也许:
tsc 2>&1 >tsc.out |
perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", , -1, -1, )/e'
管道最初将标准输出设置为 Perl; 2>&1
也在那里发送标准错误; >tsc.out
更改标准输出,因此它转到文件 tsc.out
,而标准错误则转到管道。
我有要重写和修改一些数值的输入字符串:
输入:src/main.tsx(2,31): error TS2304: Cannot find name 'foo'.
期望输出:src/main.tsx:1:30: error: TS2304: Cannot find name 'foo'.
注意:
- 数值减1了。
error
是动态的。也可以是warning
.- 该命令会将输入通过管道传递给它 (
tsc | MAGIC_HAPPENS_HERE
)。如果有错误,那么这个命令应该传递错误。
到目前为止,我有以下内容:
sed -E "s/^([^(]+)\(([0-9]+),([0-9]+)\): ((warning)|(error)) (.*)/::: : /"
除数字操作外,此方法有效。根据我的阅读,我认为 sed
不是完成这项工作的正确工具。我查看了 awk
但遇到了正则表达式捕获组的问题。
我正在使用 MacOS。该命令不需要是可移植的。我很高兴使用 brew
.
能否请您尝试以下。
awk '
match([=10=],/\([^)]*/){
value=substr([=10=],RSTART+1,RLENGTH-1)
num=split(value,array,",")
for(i=1;i<=num;i++){
val=(val?val":":"")array[i]-1
}
part_2=substr([=10=],RSTART+RLENGTH+1)
sub(/error/,"error:",part_2)
print substr([=10=],1,RSTART-1) ":" val part_2
value=part_2=""
}' Input_file
输出如下。
src/main.tsx:1:30: error TS2304: Cannot find name 'foo'.
说明:为以上代码添加详细说明。
awk ' ##Starting awk program here.
match([=12=],/\([^)]*/){ ##Using match function to match regex from ( till ) in line.
value=substr([=12=],RSTART+1,RLENGTH-1) ##Creating variable value which has value of sub-string from RSTART+1 to RLENGTH-1.
num=split(value,array,",") ##Using split, to split the value into an array named array.
for(i=1;i<=num;i++){ ##Running for loop from i=1 to till value of num(which is length of array).
val=(val?val":":"")array[i]-1 ##Creating variable val whose value is subtraction of array[i] value with 1 and keep concatenating to its own value.
}
part_2=substr([=12=],RSTART+RLENGTH+1) ##Creating variable part_2 whose value is rest of line after matched regex.
sub(/error/,"error:",part_2) ##Substituting string error with error: here in rest of the line.
print substr([=12=],1,RSTART-1) ":" val part_2 ##Printing sub-string from 1 to till match found, :, val and part_2 variables here.
value=part_2="" ##Nullify variables value and part_2 here.
}' Input_file ##Mentioning Input_file name here.
我同意 sed
不是合适的工具。由于过时(或者可能只是过时),我会使用 Perl:
$ cat data
src/main.tsx(2,31): error TS2304: Cannot find name 'foo'.
$ perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", , -1, -1, )/e' data
src/main.tsx:1:30: error: TS2304: Cannot find name 'foo'.
$
正则表达式延迟匹配所有内容,直到“(nn,mmm):
”后跟 'word',捕获两个数字以及括号和单词之前的内容。然后,它使用 /e
修饰符('evaluate the right side as an expression' — 请参阅 Regexp Quote-Like Operators)使用 sprintf()
进行减法以格式化信息。 'word' 将捕获 error
或 warning
或任何其他所有字母后跟空格的内容。您可以使用 \S+
代替 \w+
来捕获任何非 space 字符序列。我假设分隔符是单个空格;如果需要,您可以使用 \s+
代替空格,以匹配任何非空的白色序列 space。 (-p
选项仅表示“从命名文件或标准输入中读取行,如果没有命名文件,执行 -e '…script…'
中的操作并打印结果。)
已使用 5.18.4(/usr/bin/perl
在 macOS Mojave 10.14.6 上)和 5.30.0 进行测试。
如果您有一个产生错误的进程,那么您需要确保将错误发送到 Perl 脚本 — 那是 shell 脚本而不是其他任何东西。
tsc 2>&1 |
perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", , -1, -1, )/e'
如果您需要将命令的标准输出(修改后的问题中的tsc
和上面的shell脚本片段)转到其他地方,那么您需要小心(另请参见How to pipe stderr and not stdout),但也许:
tsc 2>&1 >tsc.out |
perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", , -1, -1, )/e'
管道最初将标准输出设置为 Perl; 2>&1
也在那里发送标准错误; >tsc.out
更改标准输出,因此它转到文件 tsc.out
,而标准错误则转到管道。