Извлечь строки с помощью разделителя и добавить как столбец в файле

попробуйте

 for x in */*/*.h5
 do
    mv "$x" "$(dirname $(dirname $x))"
 done

, если в именах каталогов нет странных символов.

Или, альтернативно:

ls */*/*.h5 | awk -F/ '{print "mv \"%s\"  \"%s/%s\" \n",$0,$1,$3 ;}' | bash

вы можете удалить | bash , чтобы получить предварительный просмотр.

2
12.06.2018, 14:18
8 ответов

Awksolución (suponiendo que el número de "claves" (contenidas en el primer campo$1)siempre correspondería al número de "valores" (contenidos en el segundo campo$2)):

awk '$1 ~ /,/{
         len = split($1, keys, ",");
         split($2, vals, ",");
         for (i = 1; i <= len; i++) print keys[i], vals[i];
         next
    }1' file

La ​​salida:

a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
2
27.01.2020, 21:50

Usando awk:

awk '{gsub(","," "); for(i=0;i<NF/2;i++) print $(i+1),$(i+1+NF/2)}' file     

Después de eliminar la coma de cada línea, el script recorre la mitad de los parámetros de cada línea para imprimir los primeros campos junto con el campo de la segunda mitad de la línea.

1
27.01.2020, 21:50

Conperl

$ perl -lane '@v=split/,/,$F[1]; $i=0;
              print "$_ $v[$i++]" for split/,/,$F[0]' ip.txt
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8

Divida la primera/segunda columna, inicialice el contador de índice y luego imprima los pares iterando sobre la división de la otra columna

La opción

-adividirá automáticamente -la línea de entrada en espacios en blanco y tendrá los resultados en la matriz @F

3
27.01.2020, 21:50

"usando secuencias de comandos de shell" --esto es bash:

while read -r key value; do
    IFS=, read -ra keys <<<"$key"
    IFS=, read -ra vals <<<"$value"
    for ((i=0; i < ${#keys[@]}; i++)); do
        echo "${keys[i]} ${vals[i]}"
    done
done <<END
a 1
b 2
c,d,e 3,4,5
f 6
g,h 7,8 
END
1
27.01.2020, 21:50

С гну сэд

sed -E ':A;s/([^,]*),([^ ]*) ([^,]*),(.*)/\1 \3\n\2 \4/;tA' infile
0
27.01.2020, 21:50

Один из способов сделать это с помощью редактора sed:

sed -e '
   s/,/\n/
   s/\(\n.*[[:blank:]]\)\([^,]*\),/ \2\1/
   P;D
' input.file

Рабочий:

  • Вырезать начальный элемент, разделенный запятой -, из 2-го поля.
  • Затем добавьте этот элемент в элемент первого поля, разделенный запятой -.
  • Напечатайте начальный элемент 1-го поля и удалите его после этого.
  • Повторяйте эту процедуру с тем, что осталось в пространстве шаблонов, пока оно не станет пустым.

Другой метод, использующий Perl,:

perl -lane '
   my($kref, $vref, %h) = map { [split /,/] } @F[0,1];
   @h{@$kref} = @$vref;
   print "$_  $h{$_}" for @$kref;
' input.file

Здесь показан другой способ:

perl -lpe 'print "$1 $3" while s/^([^,]*),(.*\h)([^,]*),/$2/' input.file

Работа:

  • Посмотрите на регулярное выражение таким образом:(Perl читает строку за раз из файла ), затем :
    • ^ ([^,]*)должен выбрать первый -элемент текущей строки, разделенный запятой -. Это хранится в переменной $1.
    • (. *\h)должен сохранить для следующей итерации цикла while промежуточное содержимое, начиная со второго элемента, разделенного запятой -первого поля, до начала второго элемента, разделенного запятой -второе поле. Это хранится в переменной $2.
    • ([^,]*)должен выбрать начальный элемент, разделенный запятой -, из второго поля текущей строки. Он сохраняется в переменной $3.
    • Теперь «$1 $3» выводится в STDOUT, а строка сокращается до $2. Цикл while теперь выполняет операцию снова и снова в этой отредактированной строке, которая составляет $2 от предыдущей строки,..... это повторяется до тех пор, пока s/// не завершится успешно. Неудача наступает, когда заканчиваются запятые. В этот момент то, что осталось в строке «c 5», выводится в STDOUT в соответствии с поведением Perl по умолчанию в режиме -p.
  • Удалить элементы, разделенные начальной запятой -из первого и второго полей.
  • Распечатать эти элементы, а также уменьшить текущую запись путем удаления.
  • Перебрать текущую запись, если в ней есть 2 запятые.
  • Последняя пара печатается автоматически -из-за опции -p в Perl.

perl -lane '
   my($kref, $vref) = map { [split /,/] } @F;
   print shift @$kref, " ", shift @$vref while @$kref && @$vref;
' input.file

Работа:

  • ключи хранятся в массиве @$kref, соответствующие значения — в @$vref. Обратите внимание, что здесь нет хэшей.
  • одновременно напечатать верхнюю часть массивов, а затем удалить верхнюю часть... полоскать, повторять, пока оба массива не пусты -.

Выход:

a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
2
27.01.2020, 21:50

Здесь много решений, запрограммированных на perl, awk, sed, bash,... но нет скриптового -решения.

# /bin/bash
f="yourFile"
paste -d' ' <(cut -d' ' -f1 "$f" | tr, '\n') <(cut -d' ' -f2 "$f" | tr, '\n')

или пишется иначе

# /bin/bash
f() { cut -d' ' -f"$1" yourFile | tr, '\n'; }
paste -d' ' <(f 1) <(f 2)
0
27.01.2020, 21:50

Извините за путаницу...

perl -pe '1 while s/(.*),(.*\h)(.*),/$1 $3\n$2/' infile

Каждая замена извлекает последнюю пару:

a,b,c 1,2,3  →  a,b 1,2  →  a 1
                c 3         b 2
                            c 3
0
27.01.2020, 21:50

Теги

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