【问题标题】:Issue using sed into a loop使用 sed 进入循环的问题
【发布时间】:2020-09-06 11:03:06
【问题描述】:

问题描述: 我正在尝试读取文件 test.csv,并在每行的末尾添加一个变量 $lastid(例如,例如 35)。 但是这个变量需要每两行递增一次。

期望: 我期望得到: 对于行尾的第 1 行和第 2 行 ",36"。 对于行尾的第 3-4 行“,37”。 对于行尾的第 5-6 行“,38”。 等等……

脚本代码:

set -x ##debug mode on
lines=$( wc -l < test.csv ) ## you count the total of lines
lines=$((lines+1)) ## you increment it
g=$lastid   ## this is the variable of my lastid_game from my database (let's say 35 for the example)
i=1
j=1
while [ $j -le $lines ] ## while my lines number is lower or equal than the total of lines
do
    if [ $(( $j%2 )) -eq 0 ] ## if my line number is even
    then
        echo "number "$j" is even" ## I display it
        j=$(( $j+1 )) ## I increment my lines
        sed -e "s/$/,$g/" test.csv > test1.csv
    else
        echo "number "$j" is odd" ## I display my line is odd
        g=$(( $g+1 )) ## I increment my id_game
        j=$(( $j+1 )) ## I increment my lines
        sed -e "s/$/,$g/" test.csv > test1.csv
    fi
done
set +x ##debug mode off

test.csv 的内容:

a,b,c,d,e,f
a,b,c,d,e,f
a,b,c,d,e,f
a,b,c,d,e,f
a,b,c,d,e,f
a,b,c,d,e,f
a,b,c,d,e,f
a,b,c,d,e,f

当前输出:(我认为这很好)

++ wc -l
+ lines=46
+ lines=47
+ g=35
+ i=1
+ j=1
+ '[' 1 -le 47 ']'
+ '[' 1 -eq 0 ']'
+ echo 'number 1 is odd'
number 1 is odd
+ g=36
+ j=2
+ sed -e 's/$/,36/' test.csv
+ '[' 2 -le 47 ']'
+ '[' 0 -eq 0 ']'
+ echo 'number 2 is even'
number 2 is even
+ j=3
+ sed -e 's/$/,36/' test.csv
+ '[' 3 -le 47 ']'
+ '[' 1 -eq 0 ']'
+ echo 'number 3 is odd'
number 3 is odd
+ g=37
+ j=4
+ sed -e 's/$/,37/' test.csv
+ '[' 4 -le 47 ']'
+ '[' 0 -eq 0 ']'
+ echo 'number 4 is even'
number 4 is even
+ j=5
+ sed -e 's/$/,37/' test.csv
+ '[' 5 -le 47 ']'
+ '[' 1 -eq 0 ']'
+ echo 'number 5 is odd'
number 5 is odd
+ g=38
+ j=6
+ sed -e 's/$/,38/' test.csv
+ '[' 6 -le 47 ']'
+ '[' 0 -eq 0 ']'
+ echo 'number 6 is even'
number 6 is even
+ j=7
+ sed -e 's/$/,38/' test.csv
+ '[' 7 -le 47 ']'
+ '[' 1 -eq 0 ']'
+ echo 'number 7 is odd'

当前结果: test1.csv 给了我以下结果:

,59a,b,c,d,e,f
,59a,b,c,d,e,f
,59a,b,c,d,e,f
,59a,b,c,d,e,f
,59a,b,c,d,e,f
,59a,b,c,d,e,f
,59a,b,c,d,e,f
a,b,c,d,e,f,59

问题一: id 总是一样的。

问题 2: id 没有增加,但似乎只显示最后一个计算出来的。

请问有谁知道可能是什么问题?

【问题讨论】:

标签: bash shell awk sed


【解决方案1】:

通常使用awk 来解析文件:

awk '{print $0 "," 36+int((NR-1)/2)}'
  • NR - 当前行号,以 1 开头
  • (NR-1)/2 - 从当前行号计算数字。所以一个数字序列,例如:{0, 0.5, 1, 1.5, 2, 2.5, ....etc.} 代表每个行号
  • int(...) - 向下舍入为整数
  • 36+ 你想从 36 开始
  • $0当前行
  • ","在数字和当前行之间添加逗号

注意事项:

  • sed -e "s/$/,$g/" test.csv &gt; test1.csv 正在为每个循环覆盖同一个文件 一遍又一遍
  • bash 有算术扩展,你可以使用if ((j &lt;= lines)); then 来获得更清晰的代码。

【讨论】:

    【解决方案2】:

    请您尝试关注一下。

    val="35"  ##shell variable.
    awk -v var="$val" 'BEGIN{FS=OFS=","} FNR%2!=0{++var} {$(NF+1)=var} 1' Input_file
    

    说明:为上述添加详细说明。

    awk -v var="$val" '      ##Starting awk program from here and creating awk variable var which has val in it.
    BEGIN{                   ##Starting BEGIN section of awk program from here.
      FS=OFS=","             ##Setting field and output field separator as comma here.
    }
    FNR%2!=0{                ##Checking condition if line is odd line number wise then do following.
      ++var                  ##increase value of var with 1 here.
    }
    {
      $(NF+1)=var            ##Adding 1 more field which has var field in it for current line.
    }
    1                        ##1 will print current line here.                        
    ' Input_file             ##Mentioning Input_file name here.
    

    【讨论】:

    • 您好,非常感谢您的反馈。它几乎是正确的(id 每两行递增一次,但它在每行的开头输入它,期望最后一行正确地结束。
    • @CédricDirr,您需要在脚本中创建一个名为 var=35 的 shell 变量,或者如果您不想创建 shell 变量,然后将我的 awk 更改为 awk -v var="35" .....,它应该会飞那么,请在您检查后告诉我。
    • 有效!我的文件在记事本++ 中的EOL 转换窗口上,而不是在Linux 上。谢谢一百万!
    • @CédricDirr,您可以看到此链接stackoverflow.com/help/someone-answers 有人能在 SO 上获得有用的答案吗 :)
    【解决方案3】:

    这可能对你有用(GNU sed):

    var=36
    sed '1{x;s/^/'$var'/;x};                   # prime the counter
         1~2,+1{G;s/\n/,/};                    # append the counter
         2~2{x;s/.*/expr & + 1/e;x}' file      # increment the counter
    

    地址范围1~2,+1表示1步2加1或从第1行开始每两行。

    地址2~2表示2步2或从2开始每隔一行。

    最后一次替换的 RHS 使用命令 expr 通过评估表达式的 e 标志来增加存储的变量。

    【讨论】:

      【解决方案4】:
      1. 使用 GNU seqpastewc 和一些带有 有点捏造来弥补floating point round-off error

        n=35; seq -f '%.0f' $n.9 .5 $(($n + $(wc -l < test.csv)/2 )).5 | 
        paste -d , test.csv -
        
      2. 使用jotpastewc

        n=36 p=$(wc -l < test.csv) ; jot  $p $n $((p+n)) .499999999 |
        paste -d , test.csv -
        

      任一输出:

      a,b,c,d,e,f,36
      a,b,c,d,e,f,36
      a,b,c,d,e,f,37
      a,b,c,d,e,f,37
      a,b,c,d,e,f,38
      a,b,c,d,e,f,38
      a,b,c,d,e,f,39
      a,b,c,d,e,f,39
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-23
        • 2017-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-02
        • 1970-01-01
        相关资源
        最近更新 更多