Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash复制每行,再打印3行,更改结尾_Bash_Shell_Awk_Sed - Fatal编程技术网

Bash复制每行,再打印3行,更改结尾

Bash复制每行,再打印3行,更改结尾,bash,shell,awk,sed,Bash,Shell,Awk,Sed,输入文件由多行组成,如 0 1 0 0 0 1 1 0 0 0 / 1 0 / 1 0 / 1 0 1 0 1 0 0 0 0 -1 3 / 4 1 / 4 1 / 2 我想复制输入中的每一行,在原始行下面插入3个副本,并修改末尾的分数。我希望输出是 0 1 0 0 0 1

输入文件由多行组成,如

   0     1     0     0     0     1     1     0     0    0 / 1    0 / 1    0 / 1
   0     1     0     1     0     0     0     0    -1    3 / 4    1 / 4    1 / 2
我想复制输入中的每一行,在原始行下面插入3个副本,并修改末尾的分数。我希望输出是

   0     1     0     0     0     1     1     0     0    0 / 1    0 / 1    0 / 1
   0     1     0     0     0     1     1     0     0    0 / 1    1 / 2    1 / 2
   0     1     0     0     0     1     1     0     0    1 / 2    0 / 1    1 / 2
   0     1     0     0     0     1     1     0     0    1 / 2    1 / 2    0 / 1
   0     1     0     1     0     0     0     0    -1    3 / 4    1 / 4    1 / 2
   0     1     0     1     0     0     0     0    -1    3 / 4    3 / 4    0 / 1
   0     1     0     1     0     0     0     0    -1    1 / 4    1 / 4    0 / 1
   0     1     0     1     0     0     0     0    -1    1 / 4    3 / 4    1 / 2
对分数的修改遵循该模式

(0,0,0)  <- original fractions
(0,+1/2,+1/2)
(+1/2,0,+1/2)
(+1/2,+1/2,0)
必须从中减去1

so 5/4 -> 1/4

希望将此解决方案添加到当前的bash脚本中。我显示为“输入”的内容是迄今为止脚本的结果。也许是一个awk或sed命令来实现所需的结果?

下面的Perl脚本按照您要求的方式处理分数。它用来做数学运算

#!/usr/bin/perl
use strict;
use warnings;

use Number::Fraction;

while (<>) {
    print;
    my @cols = split /(\s+)/;
    for my $modify ([0, 1, 1], [1, 0, 1], [1, 1, 0]) {
        my @fractions = map 'Number::Fraction'->new(@cols[@$_]),
            [-18, -14],[-12, -8], [-6, -2];
        my @newcols;
        for my $i (0 .. 2) {
            if ($modify->[$i]) {
                $fractions[$i] += 'Number::Fraction'->new(1, 2);
                $fractions[$i] -= 1 if $fractions[$i] >= 1;
            }
            push @newcols, $fractions[$i];
        }
        s{/}{ / }, s{^0$}{0 / 1} for @newcols;  # Format the fractions.
        print @cols[0..19], $newcols[0],
              $cols[25],    $newcols[1],
              $cols[31],    $newcols[2],
              "\n";
    }

}
#/usr/bin/perl
严格使用;
使用警告;
使用数字::分数;
而(){
打印
my@cols=split/(\s+);
对于我的$modify([0,1,1],[1,0,1],[1,1,0]){
my@fractions=map'Number::Fraction'->新建(@cols[@$)),
[-18, -14],[-12, -8], [-6, -2];
我的@newcols;
对于我的$i(0..2){
如果($modify->[$i]){
$fractions[$i]+='Number::Fraction'->新的(1,2);
如果$fracts[$i]>=1,则$fracts[$i]-=1;
}
推送@newcols,$sections[$i];
}
@newcols;#的{/}{/},s{^0$}{0/1}格式化分数。
打印@cols[0..19],$newcols[0],
$cols[25],$newcols[1],
$cols[31],$newcols[2],
“\n”;
}
}

awk
救援

$ awk 'BEGIN{FS=OFS="\t"} 
       function addHalf(v) {split(v,a," / ");                 # split num/denom
                            n=2*a[1]+a[2]; d=2*a[2];          # add 1/2
                            if(n>=d) n-=d;                    # modulus 1
                            while(!(n%2 || d%2)) {n/=2;d/=2}  # normalize if both even
                            return n " / " d}

     {print;
      for(i=2;i>=0;i--)                   # iterate over last three fields
        {j=NF-(i+1)%3;   k=NF-(i+2)%3;    # compute indices
         tj=$j;          tk=$k;           # save values
         $j=addHalf(tj); $k=addHalf(tk);  # modify selected indices
         print;                           # print modified line
         $j=tj;          $k=tk}}' file    # revert to saved values

这将帮助您使用GNU awk for true multi-dimensional Array、gensub()和\s/\s速记识别原始分数和要应用于每个分数的增量:

$ cat tst.awk
BEGIN {
    split("\
            (0,0,0)             \
            (0,+1/2,+1/2)       \
            (+1/2,0,+1/2)       \
            (+1/2,+1/2,0)       \
        ",modRows,/[[:space:])(]+/)

    for (i=1; i in modRows; i++) {
        row = modRows[i]
        if ( row ~ /\S/ ) {
            deltas[++numRows][1]
            numCols = split(row,deltas[numRows],/,/)
        }
    }
}

{
    head = gensub(/^((\s*\S+){9})(.*)/,"\\1",1)
    tail = gensub(/^(\s*(\S+\s+){9})(.*)/,"\\3",1)
    tail = gensub(/ ([^0-9]) /,"\\1","g",tail)

    split(tail,fracts)

    for (rowNr=1; rowNr <= numRows; rowNr++) {
        printf "%s", head
        for (colNr=1; colNr <= numCols; colNr++) {
            fract = fracts[colNr]
            delta = deltas[rowNr][colNr]
            printf "%s%s", OFS, addDelta(fract,delta)
        }
        print ""
    }
}

function addDelta(oldFract,delta,       newFract) {
    newFract = "(" oldFract " + " delta ")"    # <-- do the math here!
    return newFract
}

<>你需要做的就是把你计算出来的任何数学加在脚本底部AdDeltSase()函数中的每个点上的计算。

当你在做中等复杂的算术运算(添加分数和模1)时,我会考虑为此编写小Perl或Python脚本。虽然它在bash和awk中是可以自己实现的(sed我不确定——可能吧?),但可读性会受到很大的影响。我应该提到我对脚本编写是新手,因此我对perl和pythonSo不熟悉。您是否会要求我们每一步都做您的工作(或家庭作业)?在前面的问题之后,您要求生成此问题的输入。工作吧,如果你被困在某件事上,我们会帮助你,但不是全部写下来!过去的帖子:那么……仅供参考,既然你在个人资料中说“我想加入一个计算研究小组”,你可能想学习python。Python有很多数学、统计、图形工具。。。模块。到目前为止,Bash对数学不太好!Bash更适合系统管理员,而不是复杂的逻辑。我发布了一个解决方案,但应该说这是一种可怕的工作格式,它既不是机器也不是人类友好的!哦,我的天哪,当你说它既不是机器也不是人类友好型的时候,你不是在开玩笑。但是考虑到OP对其编程经验的评价,将其保存在AWK中可能是一个很好的选择,这样OP才能更好地理解它。第10行:(FILENAME=input.txt FNR=1)致命:尝试访问字段-1我们是否应该迭代最后9个字段并跳过/symbol?字段选项卡是否分开?如果没有,你就不会有最后三个字段,而只有一个。要分开每一个“列”,我只需按适当的空格次数,这是不对的。那么,您如何以原子方式定义最后三个字段?它们也是空间分隔的。您可以使用
unexpand-t5 file>file.tsv
change 5将格式更改为任意数量的空格。或者,类似于
sed
。主要问题是您不应在字段中使用无效字符的字段分隔符。尝试使用您的代码将产生以下结果:
第41行:use:command未找到第42行:use:command未找到第44行:use:command未找到第46行:意外标记附近的语法错误
)'第46行:
while(){'
我已经检查过了,我有PerlV5.10。1@RobS.您是如何运行Perl脚本的?要么
chmod u+x
然后运行
/path/to/script input/file
,要么使用
Perl path/to/script input/file
运行它。您显示的错误来自shell,而不是Perl。现在我收到了
-bash:./Perl\u输出:bin/Perl:bad解释器:没有这样的文件或目录
无法在@INC中找到Number/Fraction.pm(@INC包含:/usr/local/lib64/perl5/usr/local/share/perl5/usr/lib64/perl5/vendor\u perl/usr/share/perl5/vendor\u perl perl/usr/lib64/perl5/usr/share/perl5。)在perl_输出行5.BEGIN失败——编译在perl_输出行5中止。
使用您列出的两种方法,您需要通过运行
cpan Number::Fraction
来安装Number::Fraction。但是,首先,您需要配置
cpan
以正确安装库,可能是通过。我收到错误BEGIN:not found synta命令意外标记附近的x错误
“(0,0,0)(0,+1/2,+1/2)(+1/2,0,+1/2)(+1/2,+1/2,0)”,modRows,/[:space:'try03.bash:第47行:
”,modRows,/[:space:])(]+/)“然后你把我的脚本复制/粘贴错了,或者犯了其他错误。我无法帮助你找出错误是什么,因为我看不到你的代码。”。
$ cat tst.awk
BEGIN {
    split("\
            (0,0,0)             \
            (0,+1/2,+1/2)       \
            (+1/2,0,+1/2)       \
            (+1/2,+1/2,0)       \
        ",modRows,/[[:space:])(]+/)

    for (i=1; i in modRows; i++) {
        row = modRows[i]
        if ( row ~ /\S/ ) {
            deltas[++numRows][1]
            numCols = split(row,deltas[numRows],/,/)
        }
    }
}

{
    head = gensub(/^((\s*\S+){9})(.*)/,"\\1",1)
    tail = gensub(/^(\s*(\S+\s+){9})(.*)/,"\\3",1)
    tail = gensub(/ ([^0-9]) /,"\\1","g",tail)

    split(tail,fracts)

    for (rowNr=1; rowNr <= numRows; rowNr++) {
        printf "%s", head
        for (colNr=1; colNr <= numCols; colNr++) {
            fract = fracts[colNr]
            delta = deltas[rowNr][colNr]
            printf "%s%s", OFS, addDelta(fract,delta)
        }
        print ""
    }
}

function addDelta(oldFract,delta,       newFract) {
    newFract = "(" oldFract " + " delta ")"    # <-- do the math here!
    return newFract
}
$ gawk -f tst.awk file
   0     1     0     0     0     1     1     0     0    (0/1 + 0)       (0/1 + 0)       (0/1 + 0)
   0     1     0     0     0     1     1     0     0    (0/1 + 0)       (0/1 + +1/2)    (0/1 + +1/2)
   0     1     0     0     0     1     1     0     0    (0/1 + +1/2)    (0/1 + 0)       (0/1 + +1/2)
   0     1     0     0     0     1     1     0     0    (0/1 + +1/2)    (0/1 + +1/2)    (0/1 + 0)
   0     1     0     1     0     0     0     0    -1    (3/4 + 0)       (1/4 + 0)       (1/2 + 0)
   0     1     0     1     0     0     0     0    -1    (3/4 + 0)       (1/4 + +1/2)    (1/2 + +1/2)
   0     1     0     1     0     0     0     0    -1    (3/4 + +1/2)    (1/4 + 0)       (1/2 + +1/2)
   0     1     0     1     0     0     0     0    -1    (3/4 + +1/2)    (1/4 + +1/2)    (1/2 + 0)