повторите строку, разделив одно поле

Это только работает потому что tr не изменяет размер файла.

1<>file открывается file как стандартный вывод в режиме перезаписи. (<> назван режимом чтения-записи, но начиная с небольшого количества чтения программ stdout, более полезно сфокусироваться на том, что это на самом деле делает.)

Обычно, когда Вы перенаправляете вывод (>file), файл открыт в режиме "записи", который заставляет его или быть созданным или освобожденным. Другая общая опция >>file, "добавьте" режим, который пропускает шаг, где файл освобожден, но помещает весь вывод в конец. 1<>file также пропуски, освобождающие файл, но это помещает курсор записи в начале файла. (Вам нужно 1 потому что <> значения по умолчанию к перенаправлению stdin, нет stdout).

Это только достаточно редко полезно, так как очень немного утилит так точны в своей модификации. Другой случай был бы поиском и заменой, где замена является точно той же длиной как оригинал. (Более короткая замена не работала бы также, потому что файл не является усеченным в конце; если бы вывод короче, чем оригинал, Вы закончили бы с любым используемым, чтобы быть в конце файла, все еще являющегося в конце файла.)

3
09.12.2014, 01:52
7 ответов

Вы можете использовать awk для разделения Первый столбец:

~$ awk '{split($1,a,";"); $1="";for (i in a){print a[i],$0}}' myfile
K00001  0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 0 52 0 0 0 6 0
K00004  0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 0 52 0 0 0 6 0
K00008  0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 0 52 0 0 0 6 0

Вы разбили первый столбец на ; ; ( ( ( ( ( ( ($ 1, A, «;») ), а затем вы удаляете его, чтобы распечатать целое (новое ) Линия ( $ 0 ) Для каждого элемента в массиве.


Как предложено в комментарии, после редактирования, мы видим, что вкладки используются в качестве сепаратора. Чтобы использовать вкладку в качестве сепаратора вывода полей, вы можете использовать ofS = «\ T» , например, в начнется часть awk. Кроме того, пустое поле вставляется с $ 1 = "" . Итак, вместо печати [I] $ 0 , лучше установить $ 1 на A [I] , а затем печать $ 0 :

~$ awk 'BEGIN{OFS="\t"}{split($1,a,";"); for (i in a){$1=a[i];print}}' myfile
K00001  0       0       34      0       0       0       0       0       0       0       0       0       0       0       0       0       36      0       0       52      0       0       0       6       0
K00004  0       0       34      0       0       0       0       0       0       0       0       0       0       0       0       0       36      0       0       52      0       0       0       6       0
K00008  0       0       34      0       0       0       0       0       0       0       0       0       0       0       0       0       36      0       0       52      0       0       0       6       0
7
27.01.2020, 21:07

Это должно делать то, что ты хочешь. В основном, мы помещаем первое поле (клавиши) в $k, а остальные поля в $f путем разбиения на \t и ограничения разбиения на первые 2 поля. Затем мы разделим клавиши на ; и распечатаем каждую клавишу вместе с оставшимися полями на своей строке.

perl -nle '($k, $f) = split "\t", $_, 2; print "$_\t$f" for split ";", $k'

-n циклов по входу. Вы можете либо перевести свой файл на perl, либо передать имя входного файла в конце командной строки. -l включает автоматическое управление окончанием строки.

4
27.01.2020, 21:07

Я думаю, вам не нужно переименовать файлы. Вы можете преобразовать имена файлов на лету (First Sed), сравните их с датой (AWK) и преобразовывать соответствующие имена файлов обратно (второй SED).

find parent/directory -maxdepth 1 -type d -name 'bkp_*'                | \
sed 's#parent/directory/bkp_\(..\)\(..\)\(....\)#\3\2\1#'              | \
awk -v date=$(date --date='3 months ago' +%Y%m%d) '$0<$date{print $0}' | \
sed 's#\(....\)\(..\)\(..\)#parent/directory/bkp_\3\2\1#'              | \
xargs rm -r

Вы должны проверить это без деталей RM Xargs RM!

-121--139844-

файл awk

 {
   split($1,A,";") ;
   for ( a in A )
    {
    printf "%s",A[a] ;
    for(i=2;i<=NF;i++) printf "\t%s",$i ;
    printf "\n" ;
    }
  }

где разделен

  • (1, а 1, а, «;») , введенный в все подпугивающее значение $ 1
  • для (A в A в A ) Структура через значение
  • printf «% s», A [A]; ; Распечатайте первое значение
  • для (i = 2; i <= nf; i ++) printf "\ T % s ", $ i; Печать оставшегося значения в командной строке
  • printf" \ N "; Новая строка
2
27.01.2020, 21:07

Еще один Perl-одинлайнер.

$ perl -pe 's/^([^;]+);([^;]+);(\S+)\s+(.*)/$1 $4\n$2 $4\n$3 $4/' file
K00001 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00004 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00008 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0

Другой сед-один лайнер.

$ sed 's/^\([^;]\+\);\([^;]\+\);\([^ ]\+\) \+\(.*\)/\1 \4\n\2 \4\n\3 \4/' file
K00001 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00004 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00008 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
1
27.01.2020, 21:07

Дольше Perl версия, которая позволяет получить доступ к данным на ключ и дополнительный процесс, если требуется. Это также не использует захват от регулярных выражений.

#!/usr/bin/perl
use warnings; 
use strict;

my %hash; 

while ( my $line = <> ){
    #splitting the line into two parts at the first TAB.
    my ($keys, $value) = split (/\t/ , $line, 2);

    #splits the set of keys at each semicolon
    my @key = split /;/, $keys;

    #@key is used in scalar context here to get the number of keys.
    #this is used to determine how many values we need to put into the hash
    @hash{@key} = ($value) x @key; 
}

for my $key (keys %hash){
    print "$hash{$key}\n"; 
}

Дальнейшее чтение:

0
27.01.2020, 21:07

С sed:

sed 's/^\([^[:blank:];]*\);\([^[:blank:]]*\)\(.*\)/\1\3\
\2\3/;P;D'
3
27.01.2020, 21:07

Медленный рабочий день, так что вот питон решение

python3 -c 'import sys
x = (l.partition("\t") for l in sys.stdin)
x = ((l[0].split(";"), l[1] + l[2]) for l in x)
for a in x:
  print(*a[0], sep=a[1], end=a[1])
' <file
0
27.01.2020, 21:07

Теги

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