如何使用AWK在每个单元格中反向打印字符串的字符?

时间:2018-08-01 03:13:52

标签: string awk printing field reverse

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;
}

{
    $1 = reverse_print($1) ; 
    $2 = reverse_print($2) ; 
    $3 = reverse_print($3) ; 
    $4 = reverse_print($4) ; 
    $5 = reverse_print($5) ; 
    $6 = reverse_print($6) ; 
    print;
}

END {}

它可以很好地工作。

这是我想要的输出:

hteB        54      00.4        0       0       270.
ynnaD       33      57.3        0^      0       980.

我已经很努力地思考了,但是仍然无法弄清楚使用循环的地方错了。

谁能告诉我为什么?

3 个答案:

答案 0 :(得分:2)

您正在函数内部和外部使用相同的变量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.

答案 1 :(得分:1)

请您尝试以下操作。(该程序仅在GNU awk上进行了测试,并且根据Ed ir先生的评论,这对于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

答案 2 :(得分:0)

有一个rev command in Linuxrev - 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