如何使用 AWK 在每个单元格中反向打印字符串的字符?
How can I reverse print the characters of a string in each cell using AWK?
Beth 45 4.00 0 0 .072
Danny 33 3.75 ^0 0 .089
以上是我要操作的文件
我想写一个 AWK 脚本,可以在每个单元格中反向打印字符串的字符。
代码如下:
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i) ;
print;
}
END {}
但是,它不起作用。程序不知何故死了。
我发现如果我不使用循环并像下面这样一个一个地处理每个字段,
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
print;
}
END {}
它可以很好地工作。
这是我想要的输出:
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
我想了想还是想不通我循环哪里做错了
谁能告诉我为什么?
能否请您尝试以下操作。(此程序仅在 GNU awk
上测试,并且根据 Ed 先生的评论,这也是 POSIX awk
的未定义行为)
awk '
BEGIN{
OFS="\t\t"
}
{
for(i=1;i<=NF;i++){
num=split($i,array,"")
for(j=num;j>0;j--){
val=(j<num?val:"") array[j]
}
printf "%s%s",val,(i<NF?OFS:ORS)}
val=""
}' Input_file
您在函数内外使用了相同的变量 i
。在任一位置使用不同的变量或将函数定义更改为 reverse_print(str, i)
以使函数内使用的 i
成为该函数的局部变量,而不是在调用代码中使用相同的全局变量。
您还应该将 s 和 N 函数设为本地:
function reverse_print(str, i, s, N)
但实际上代码应该写成:
$ cat tst.awk
BEGIN { OFS = "\t\t" }
function reverse_print(fwd, rev, i, n)
{
n = length(fwd)
for (i = n; i >= 1; i--)
rev = rev substr(fwd, i, 1);
return rev
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i)
print
}
$ awk -f tst.awk file
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
有一个rev
command in Linux:rev - reverse lines characterwise
。
您可以通过使用 awk 内置函数 system
调用 rev
来反转字符串,例如:
#reverse-fields.awk
{
for (i = 1; i <= NF; i = i + 1) {
# command line
cmd = "echo '" $i "' | rev"
# read output into revfield
cmd | getline revfield
# remove leading new line
a = gensub(/^[\n\r]+/, "", "1", revfield)
# print reversed field
printf("%s", a)
# print tab
if (i != NF) printf("\t")
# close command
close(cmd)
}
# print new line
print ""
}
$ awk -f reverse-fields.awk emp.data
0 00.4 hteB
0 57.3 naD
01 00.4 yhtaK
02 00.5 kraM
22 05.5 yraM
81 52.4 eisuS
Beth 45 4.00 0 0 .072
Danny 33 3.75 ^0 0 .089
以上是我要操作的文件
我想写一个 AWK 脚本,可以在每个单元格中反向打印字符串的字符。
代码如下:
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i) ;
print;
}
END {}
但是,它不起作用。程序不知何故死了。
我发现如果我不使用循环并像下面这样一个一个地处理每个字段,
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
= reverse_print() ;
print;
}
END {}
它可以很好地工作。
这是我想要的输出:
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
我想了想还是想不通我循环哪里做错了
谁能告诉我为什么?
能否请您尝试以下操作。(此程序仅在 GNU awk
上测试,并且根据 Ed 先生的评论,这也是 POSIX awk
的未定义行为)
awk '
BEGIN{
OFS="\t\t"
}
{
for(i=1;i<=NF;i++){
num=split($i,array,"")
for(j=num;j>0;j--){
val=(j<num?val:"") array[j]
}
printf "%s%s",val,(i<NF?OFS:ORS)}
val=""
}' Input_file
您在函数内外使用了相同的变量 i
。在任一位置使用不同的变量或将函数定义更改为 reverse_print(str, i)
以使函数内使用的 i
成为该函数的局部变量,而不是在调用代码中使用相同的全局变量。
您还应该将 s 和 N 函数设为本地:
function reverse_print(str, i, s, N)
但实际上代码应该写成:
$ cat tst.awk
BEGIN { OFS = "\t\t" }
function reverse_print(fwd, rev, i, n)
{
n = length(fwd)
for (i = n; i >= 1; i--)
rev = rev substr(fwd, i, 1);
return rev
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i)
print
}
$ awk -f tst.awk file
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
有一个rev
command in Linux:rev - reverse lines characterwise
。
您可以通过使用 awk 内置函数 system
调用 rev
来反转字符串,例如:
#reverse-fields.awk
{
for (i = 1; i <= NF; i = i + 1) {
# command line
cmd = "echo '" $i "' | rev"
# read output into revfield
cmd | getline revfield
# remove leading new line
a = gensub(/^[\n\r]+/, "", "1", revfield)
# print reversed field
printf("%s", a)
# print tab
if (i != NF) printf("\t")
# close command
close(cmd)
}
# print new line
print ""
}
$ awk -f reverse-fields.awk emp.data
0 00.4 hteB
0 57.3 naD
01 00.4 yhtaK
02 00.5 kraM
22 05.5 yraM
81 52.4 eisuS