Как повторить строку для каждого значения соответствующего столбца

Еще один вкладыш:

echo "Greetings 1" >> greetings.txt && echo "Greetings 2" >> greetings.txt

Я бы предпочел вариант -e, так как он дает больше контроля:

echo -e "Greeting 1\nGreetings 2\n" >> greetings.txt
1
18.03.2019, 05:15
4 ответа

awk подход:

awk 'BEGIN{OFS="\t";print "pos" OFS "COL1"}{if(NR==1){for(f=2;f<=NF;f++) c[f]=$f;}
     else{for(i=2;i<=NF;i++) print $1,c[i],$i}}' real2.txt

Вывод:

pos     COL1
18691441        COL1    C
18691441        COL2    A
18691441        COL3    G
18691572        COL1    G
18691572        COL2    C
18691572        COL3    G
18691620        COL1    A
18691620        COL2    T
18691620        COL3    G
18691716        COL1    C
18691716        COL2    G
18691716        COL3    C

OFS="\t" - разделитель полей вывода

print "pos" OFS " COL1" - печатает заголовок строку

if(NR==1){for(f=2;f<=NF;f++) c[f]=$f; - сбор имен столбцов из первой строки/заголовка

for(i=2;i<=NF;i++) print $1, c[i], $i - вывод каждого столбца (COL.. , ) значение "построчно" относительно соответствующего значения столбца pos и соответствующего имени столбца.

2
27.01.2020, 23:13

Как насчет:

while read line col1 col2 col3; 
do 
    if [[ "$line" = "pos" ]]; then
        echo "pos COL"
        continue    
    fi
    echo "$line COL1 $col1"  
    echo "$line COL2 $col2"  
    echo "$line COL3 $col3"  
done < real2.txt

output:

pos COL
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C
2
27.01.2020, 23:13
while IFS= read -r l; do
   read -r -a A <<<"$l"
   case $l in
      'pos'[\ \   ]* )
         echo "${A[@]:0:2}"
         C=("${A[@]:1}")
         ;;

      * )
         p=0 x=${A[0]}
         for e in "${A[@]:1}"; do
            echo "$x ${C[$p]} $e"
            ((p++))
         done
         ;;
   esac
done < yourfile


sed -E '
   /\n/bloop

   y/\t/ /;s/  +/ /g;s/^ +//;s/ +$//

   1{
      h
         s/ /\n/2
      x
         s/ /\n/;s/.*\n//
      x
         s/\n.*//
      b
   }

   G;s/\n/ &/

   :loop
      #  1     2     3   4   5
      s/^(\S+ )(\S+) (.*)(\n)(\S+) ?/\1\5 \2\4\1\3\4/
      /\n$/{
         /\n.*\n/!d
      }
       P
      /\n.*\n/D
   tloop

' yourfile

Результаты

pos COL1
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C

Объяснение

  • Прежде всего, мы преобразуем любые остаточные символы TAB в пробелы, затем сжимаем несколько пробелов и, наконец, обрезаем все начальные/конечные пробелы.
  • Мы делаем специальную обработку первой строки:
    • а) сделать копию строки.
    • б) отметить конец 2-го столбца на потом.
    • c) поменять местами эту отмеченную строку с копией, хранящейся в резервном пространстве.
    • d) удалить первый столбец, затем вернуться назад и в этом отображении cols1,2.
  • Для всех остальных строк (от 2 до eof) мы добавляем имена столбцов к строке.
  • Затем настройте цикл do-while, в котором на каждой итерации мы переставляем поля так, как показано, чтобы имя столбца вместе со значением выводилось на печать. Мы останавливаемся, когда видим строку, имеющую \n в конце И это единственный символ \n, оставшийся в строке. В противном случае мы просто обрываем начальную часть и возвращаемся к началу цикла.
1
27.01.2020, 23:13

Не используйте циклы оболочки для обработки текста.

Здесь awk— правильный инструмент для этой задачи. Но вам нужно вызвать его только один раз:

awk -v OFS='\t' '
  NR == 1 {print $1, "name", "value"; split($0, header); next}
  {for (i = 2; i < NF; i++) print $1, header[i], $i}' < your-file

(вариация на ответ Романа)

2
27.01.2020, 23:13

Теги

Похожие вопросы