У меня есть файл с разделителями табуляции с номером и именами, принадлежащими одному и тому же номеру в одной строке. Номер и имена разделены вкладкой. Имена связаны между собой двумя подчеркиваниями (__
). Это выглядит так:
33 Hhe.1__Hhe.2__Hhe.3__Hhe.4
Я хотел бы преобразовать его (используя командную строку) в этот вывод:
33 Hhe.1
33 Hhe.2
33 Hhe.3
33 Hhe.4
С awk
:
$ awk -F '\t|__' '{for (i=2;i<=NF;i++) {printf "%s\t%s\n", $1, $i}}' foo.txt
33 Hhe.1
33 Hhe.2
33 Hhe.3
33 Hhe.4
\t
) или двух символов нижнего подчеркивания (__
). Подобный, к какой предложенный muru: что относительно того, чтобы разделить второе поле на основе __
и затем цикличное выполнение через части?
awk 'BEGIN{FS=OFS="\t"}
{n=split($2,a,"__"); for (i=1;i<=n;i++) print $1, a[i]}' file
Это использует то, что split()
возвраты созданное число элементов.
кроме того, это устанавливает Входных и выходных Разделителей полей на вкладку, так, чтобы Вы затем не упоминали это когда Вы print
. На самом деле, FS
не должен быть установлен здесь, потому что FS
значения по умолчанию к пространству и вкладке включены.
Это возвращается:
33 Hhe.1
33 Hhe.2
33 Hhe.3
33 Hhe.4
Можно использовать остроту жемчуга для этого:
perl -ane '@l=split(/__/,$F[1]); foreach $val (@l){print $F[0],"\t",$val,"\n"}'
Пример:
$ echo "33 Hhe.1__Hhe.2__Hhe.3__Hhe.4" | perl -ane '@l=split(/__/,$F[1]); foreach $val (@l){print $F[0],"\t",$val,"\n"}'
33 Hhe.1
33 Hhe.2
33 Hhe.3
33 Hhe.4
Объяснение команд использовало:
perl -ane #read input line-wise and split line on tab
'@l=split(/__/,$F[1]); #split the second element ($F[1]) on a double _
foreach $val (@l){ #for each value, print the first element and the value.
print $F[0],"\t",$val,"\n"
}'
Еще одна острота жемчуга:
$ perl -lane 'print "$F[0]\t$_" for split(/__/,$F[1])' file
33 Hhe.1
33 Hhe.2
33 Hhe.3
33 Hhe.4
Это - та же основная идея, как существующий Perl отвечает, только короче. -a
автоматически разделения каждая строка входного файла на пробелах и делают получающиеся поля доступными как массив @F
. Так, $F[0]
1-е поле, $F[1]
второе и так далее. -n
означает, "читает каждый входной файл линию за линией и применяют сценарий, данный -e
. -l
удаляет запаздывание \n
символы от каждой входной строки и добавляют a \n
каждому print
звонить.
split(/__/,$F[1])
создает массив путем разделения 1-го поля файла на символах __
. Так, print "$F[0]\t$_" for split...
выполнит итерации по массиву, возвращенному split
назовите и распечатайте первое поле файла ($F[0]
), символ табуляции \t
и текущее поле split
массив.
Другой способ использовать Perl:
perl -lane '$,="\n"; print(map($F[0] . "\t" . $_, split("__", $F[1])))' file
perl -lane '
$,="\n";
print(map($F[0] . "\t" . $_, split("__", $F[1])))
' file
-l[octnum]
: включает автоматическую заканчивающую строку обработку. Это имеет два отдельных эффекта. Во-первых, это автоматически чавкает $/
(входной разделитель записей) при использовании с -n
или -p
. Во-вторых, это присваивается $\
(выходной разделитель записей) иметь значение octnum так, чтобы любые операторы печати имели тот разделитель, включило назад. Если octnum опущен, наборы $\
к текущему значению $/
.-a
: включает режим авторазделения при использовании с a -n
или -p
. Неявное разделение управляет к @F
массив сделан как первая вещь в неявном цикле с условием продолжения, произведенном -n
или -p
.-n
: Perl причин для принятия следующего цикла вокруг программы, которая заставляет его выполнить итерации по аргументам имени файла несколько как sed -n
или awk
:
LINE:
while (<>) {
... # your program goes here
}
-e
: может использоваться для ввода одной строки программы;
$,="\n"; print(map($F[0] . "\t" . $_, split("__", $F[1])))
; устанавливает выходного разделителя полей на символ новой строки, разделяет второе поле на __
и предварительно ожидает первое поле, сопровождаемое табулированием к каждому подполю, наконец печатая запись.% cat file
33 Hhe.1__Hhe.2__Hhe.3__Hhe.4
% perl -lane '$,="\n"; print(map($F[0] . "\t" . $_, split("__", $F[1])))' file
33 Hhe.1
33 Hhe.2
33 Hhe.3
33 Hhe.4