Предполагая, что в каталоге верхнего уровня нет файлов:
for i in *; do (cd "$i"; rm -rf *); done
или
for i in *; do (cd "$i"; for j in *; do rm -rf "$j"; done); done
Я предпочитаю последний вариант, потому что он не пытается удалить *
, если каталог пуст, и его можно легко модифицировать, чтобы включить только некоторые шаблоны файлов. Для чего-то более сложного используйте find
.
Чтобы получить первые два столбца вывода:
$ cut -d, -f1 <file | sort | uniq -c | awk -vOFS=, '{ print $2, $1 }'
A,3
B,2
C,2
D,1
Это извлекает первый столбец исходного файла, сортирует его и подсчитывает количество повторяющихся записей. awk
в конце просто меняет местами столбцы и вставляет запятую в -между ними.
Последний столбец может быть с
$ sort -u <file | cut -d, -f1 | uniq -c | awk -vOFS=, '{ print $1 }'
2
2
1
1
Это сортирует исходные данные и отбрасывает дубликаты. Затем извлекается первый столбец и подсчитывается количество дубликатов , что . awk
в конце извлекает только счетчики.
Комбинируя их с помощью bash
иpaste
:
$ paste -d, <( cut -d, -f1 <file | sort | uniq -c | awk -vOFS=, '{ print $2, $1 }' ) \
<( sort -u <file | cut -d, -f1 | uniq -c | awk -vOFS=, '{ print $1 }' )
A,3,2
B,2,2
C,2,1
D,1,1
Если вы предварительно -отсортируете данные, это может быть немного сокращено (и значительно ускорено):
$ sort -o file file
$ paste -d, <( cut -d, -f1 <file | uniq -c | awk -vOFS=, '{ print $2, $1 }' ) \
<( uniq <file | cut -d, -f1 | uniq -c | awk -vOFS=, '{ print $1 }' )
A,3,2
B,2,2
C,2,1
D,1,1
Я хотел посмотреть, можно ли решить эту проблему с помощью лайнера Perl one -, что мне удалось выяснить:
$ perl -F, -ane '$lcnt{$F[0]}++; $ccnt{$F[0]}{$F[1]}++; \
END { print "$_, $lcnt{$_}, ". (keys %{ $ccnt{$_} }). "\n" for sort keys %lcnt }' \
file
A, 3, 2
B, 2, 2
C, 2, 1
D, 1, 1
Этот -вкладыш может показаться очень сложным, но на самом деле он довольно прост, если разобрать его. В основе лежит этот механизм в Perl:
$ perl -F, -ane '...; END {... }' file
Это говорит Perl взять файл file
и перебрать его в цикле, а затем автоматически -разделить его, используя -F,
в качестве символа-разделителя, после завершения выполнить блок END {..}
один раз и выйти.
Например:
$ perl -F, -ane 'print "arg1: $F[0] arg2: $F[1]"; END { print "DONE\n" }' file
arg1: A arg2: 10
arg1: B arg2: 11
arg1: C arg2: 12
arg1: A arg2: 10
arg1: B arg2: 12
arg1: D arg2: 10
arg1: A arg2: 12
arg1: C arg2: 12
DONE
ПРИМЕЧАНИЕ.:Функция Perl auto -split автоматически помещает столбцы в массив @F
, здесь я использую элементы 1 и 2, $F[0]
и $F[1]
.
Следующее, что нам нужно сделать, это подсчитать различные биты ввода. Для этого мы воспользуемся мощью хэшей в Perl. Мы будем использовать 2, %lcnt
и %ccnt
.
ПРИМЕЧАНИЕ.:Одной из наиболее раздражающих вещей в Perl является переключение нотации при определении хэша и при доступе к нему. При доступе к нему мы переключаемся с %lcnt
на $lcnt["A"]
, но я отвлекся.
$lcnt{$F[0]}++; $ccnt{$F[0]}{$F[1]}++;
%lcnt
-количество символов из 1-го столбца %ccnt
-Двухмерный хэш, содержащий 2 координаты, для доступа к подсчету 2-го столбца ПРИМЕЧАНИЕ.:Такой подсчет позволяет выполнять уникальную функцию просто за счет того, как мы подсчитываем биты.
Например, рассмотрим содержимое хэша %lcnt
:
$ perl -F, -ane '$lcnt{$F[0]}++; $ccnt{$F[0]}{$F[1]}++; \
END { print "key: $_\n" for sort keys %lcnt }' file
key: A
key: B
key: C
key: D
Если мы хотим увидеть значение для каждого хэша:
$ perl -F, -ane '$lcnt{$F[0]}++; $ccnt{$F[0]}{$F[1]}++; \
END { print "key: $_ val: $lcnt{$_}\n" for sort keys %lcnt }' file
key: A val: 3
key: B val: 2
key: C val: 2
key: D val: 1
ПРИМЕЧАНИЕ.:Здесь мы видим, что $lcnt{$F[0]}++
проделал всю тяжелую работу по подсчету каждого символа, когда мы прошлись по файлу и добавили их в хэш %lcnt
.
Последняя часть головоломки состоит в том, чтобы отобразить всю эту собранную информацию удобным способом.Для этого мы будем использовать это вEND {...}
:
print "$_, $lcnt{$_}, ". (keys %{ $ccnt{$_} }). "\n" for sort keys %lcnt
Это перебирает список ключей из %lcnt
и печатает следующую строку:
$_, $lcnt{$_}, ". (keys %{ $ccnt{$_} }). "\n"
Если вам сложно увидеть вышеприведенную структуру, вот она в более общем виде:
A, 3, 2
^--- (keys %{ $ccnt{$_} }) ## count of unique columns for each character ($_)
^------ $lcnt{$_} ## count of each character
^--------- $_ ## character
Это создаст строку, содержащую символ ($_
), значение счетчика для этого символа ($lcnt{$_}
), а затем количество уникальных значений из 2-го столбца для каждого символа.
datamash -t, -s -g 1 count 1 countunique 2 < input.txt
Вход
A, 10
B, 11
C, 12
A, 10
B, 12
D, 10
A, 12
C, 12
Выход
A,3,2
B,2,2
C,2,1
D,1,1
С помощью небольшого sqlite3
скрипта, запускаемого из командной строки, где input.csv
— ваши входные данные:
sqlite3 -batch <<EOF
.mode csv
CREATE TABLE data (letter TEXT, number INTEGER);
.import input.csv data
SELECT letter, COUNT(*) AS lcount, COUNT(DISTINCT number) AS dcount
FROM data
GROUP BY letter ;
EOF
Это работает так
$ bash query.sqlite
A,3,2
B,2,2
C,2,1
D,1,1