Как изменить размер блока столбца

#linux #bash #awk

#linux #bash #awk

Вопрос:

У меня есть один столбец файла, содержащий много блоков, и блоки разделены > символом.

Я хочу изменить размер всех блоков до одинаковой максимальной длины, добавив под ними ноль.

Мой файл приведен ниже:

file.txt

 >
1.0
2.4
3.5
4.5
>
1.2
3.3
>
2.4
2.5
2.5
 

и мой ожидаемый результат приведен ниже

 >
1.0
2.4
3.5
4.5
>
1.2
3.3
0.0
0.0
>
2.4
2.5
2.5
0.0
 

Я пытаюсь написать скрипт, но это не удается:

 #!/bin/sh
for file in `cat file.txt`
do
    awk '{print $1 0}' $file
done
 

Ответ №1:

Основываясь на показанных вами примерах, не могли бы вы попробовать следующее. Написано и протестировано с показанными примерами в GNU awk .

 awk '
FNR==NR{
  if($0~/^>/){
     max=(max>val?max:val)
     val=""
     next
  }
  val  
  next
}
/^>/{
  if(FNR>1){
    while(count  <max){ print "0" }
  }
  count=""
  print
  next
}
{
  print
  count  
}
END{
  while(count  <max){ print "0" }
}'  Input_file  Input_file
 

Для показанных примеров вывод будет следующим.

 >
1.0
2.4
3.5
4.5
>
1.2
3.3
0
0
>
2.4
2.5
2.5
0
 

Объяснение: Добавление подробного объяснения выше.

 awk '                                   ##Starting awk program from here.
FNR==NR{                                ##Checking condition if FNR==NR here.
  if($0~/^>/){                          ##Checking condition if line starts from > then do following.
     max=(max>val?max:val)              ##Assigning max value as per max>val then assign it to max else keep it as val value.
     val=""                             ##Nullify val here.
     next                               ##next will skip all further statements from here.
  }
  val                                   ##Increasing val with 1 here.
  next                                  ##next will skip all further statements from here.
}
/^>/{                                   ##Checking condition if line starts with >
  if(FNR>1){                            ##Checking condition if this is not first line.
    while(count  <max){ print "0" }     ##Printing 0 till count is equal to max.
  }
  count=""                              ##Nullify count here.
  print                                 ##Printing current line here.
  next                                  ##next will skip all further statements from here.
}
{
  print                                 ##Printing current line here.
  count                                 ##Increasing count with 1 here.
}
END{                                    ##Starting END block of this program from here.
    while(count  <max){ print "0" }     ##Printing 0 till count is equal to max.
}' Input_file Input_file                ##Mentioning Input_file names here.
 

Комментарии:

1. если мои входные данные> 1.0> 1.2 3.3> 2.4 2.5 2.5, то это не работает

2. @sion, ответы всегда будут даны только в соответствии с показанными примерами. Поэтому, пожалуйста, попробуйте добавить образцы ввода и ожидаемого результата в самом первом вопросе, чтобы избежать путаницы позже.

3. сценарий ur основан на длине первого блока …. но мне нужно изменить размер на основе наибольшей длины блока данного файла

4. можете ли вы, пожалуйста, изменить его

5. @sion, ни один скрипт не ищет НАИБОЛЬШИЙ размер блока во всем файле, если вы пройдете объяснение, вы увидите, я объяснил это, первое чтение предназначено только для этого. Сначала прочитайте его получение максимальной длины блока, а 2-й соответственно прочитал его печать.

Ответ №2:

 awk '
NR==FNR {
    if (/^>/) c=0
    if (  c>m) m=c
    next
}
END {while (n-->0) print "0.0"}
/^>/{while (n-->0) print "0.0"; n=m} {n--}
1
' file file
 

Ответ №3:

Вы также можете попробовать этот однопроходный awk :

 awk '$0==">"{if (c amp;amp; c>max) max=c;   n; c=0; next} {r[n][  c]=$0} END {for (i=1; i<=n;   i) {print ">"; for (j=1; j<=max;   j) print (r[i][j] == "" ? "0.0" : r[i][j])}}' file

>
1.0
2.4
3.5
4.5
>
1.2
3.3
0.0
0.0
>
2.4
2.5
2.5
0.0
 

Чтобы сделать его более читаемым:

 awk '$0==">" {
   if (c amp;amp; c>max)
      max = c
     n
   c = 0
   next
}
{
   r[n][  c] = $0
}
END {
   for (i=1; i<=n;   i) {
      print ">"
      for (j=1; j<=(max>c?max:c);   j)
         print (r[i][j] == "" ? "0.0" : r[i][j])
   }
}' file