Уникальная сортировка из строки

В системах, поддерживающих Linux-подобный / proc :

#!/bin/sh
if [ $# != 2 ]
then
    echo usage: "$0" pathname commandline_regexp
    exit 1
fi
cd /proc
for p in [0-9]*
do
    exe=$(readlink $p/exe 2>/dev/null)
    if [ "$exe" = "$1" ] &&
        cat $p/cmdline 2>/dev/null | tr '\0' ' ' | grep -q -- "$2"
    then
        echo match $p
    fi
done

пример:

$ sleep 500&
[3] 18280
$ sleep 600&
[4] 18281
$ ./rpgrep /bin/sleep '.*sleep 500 $'
match 18280
$ ./rpgrep /bin/sleep '.*sleep.*00'
match 18280
match 18281

Примечания:

  • 2> / dev / null и отдельный процесс cat используются для устранения вероятности того, что процессы могут исчезнуть во время выполнения сценария.
3
24.04.2017, 11:53
5 ответов

Использование этого ответа ,

perl -MList::MoreUtils=uniq -laF'\t' -ne '
    $F[1] = join(",", uniq(sort(split(",", $F[1])))); print join("\t", @F)'

Это зависит от внешнего пакета List :: MoreUtils . Если вы не хотите устанавливать внешнюю зависимость, переопределение функции uniq - это всего лишь несколько строк Perl . (Хотя мне кажется, что он установлен как часть базовой системы в macOS.)

9
27.01.2020, 21:07

Протестировано с OpenBSD awk , GNU awk и mawk :

awk -F ',| +' '{ for (i = 2; i <= NF; ++i) { print $1, $i } }' data.in |
sort -u |
awk '{ f[$1] = (f[$1] ? f[$1] "," : "") $2 } END { for (k in f) { print k, f[k] } }'

Первый awk расширяет заданные данные в

Special c1
Special c2
Special c5
Special c7
Special c1
Special c2
Special2 C6

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

Сортировка в середине сортирует ее в

Special2 C6
Special c1
Special c2
Special c5
Special c7

. Она выполняет сортировку, используя полную строку в качестве ключа сортировки, и отбрасывает любые повторяющиеся строки.

Последний awk рекомбинирует данные в

Special c1,c2,c5,c7
Special2 C6

. Он делает это, используя первое поле в качестве ключа в ассоциативный массив, и сохраняет разделенные запятыми конкатенацию соответствующих данных во втором поле как Значение. В конце все собранные данные распечатываются.

5
27.01.2020, 21:07

gawk (GNU awk) подход:

 awk '{if($2~/.*,.*/){l=split($2,a,","); asort(a); $2=a[1]; b[a[1]]++;
      for(i=2;i<=l;i++) $2=(!b[a[i]]++)? $2","a[i] : $2 }}1' file

Вывод:

Special c1,c2,c5,c7
Special2  C6

if($2~/.*,.*/) - если у нас несколько запятых -разделенные элементы во втором поле

l=split($2,a,",") - разделение строки на части, разделенные ,.
l присваивается количество штук

asort(a) - сортирует массив подстрок

$2=(!b[a[i]]++)? $2","a[i] : $2 - с учетом уникальных предметов

5
27.01.2020, 21:07

Другой способ в одну строку:

while read line; do echo "$line" | awk '{print $1}' | tr '\n' ' ';  echo "$line" | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ',' | sed -e 's/.$//g'; echo; done < file_to_sort

Берется первый столбец каждой строки (echo $line | awk '{print $1}' | tr '\n' ' ' ;) и отсортируйте значения второго столбца, разделенные символом ',', после преобразования его в один столбец, чтобы применить sort и затем преобразовав его обратно в одну строку с исходным форматированием (echo $line | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ',').

Разбиение строк, как предложил @tripleee:

while IFS=$'\t' read first second; do printf "%s\t%s\n" "$first" "$(tr ',' '\n' <<<"$second" | sort | tr '\n' ',' | sed -e 's/.$//g';)"; done < file_to_sort
2
27.01.2020, 21:07
perl -F'\t|,' -lane 'my %h; print shift @F, "\t", join ",", sort grep !$h{$_}++, @F' dataf

Объяснение

  • -F'\t|,' => разделит поля каждой записи на массив @F на TAB или запятая символов.
  • -l также установит RS в новую строку и ORS в новую строку.
  • -a автоматически разбивает каждую запись на слова на основе FS, выбранной с помощью -F.
  • -n установит неявное чтение записи в цикле на входе И будет печатать только по запросу.
  • -e — это код Perl, который будет выполняться при каждой записи ввода на основе RS, выбранной с помощью -l выше.
  • Первый элемент будет задан как shift, а остальные элементы будут уникальными путем сохранения их в виде ключей хэша, %h, который должен генерироваться заново каждый раз, когда считывается запись. Затем уникальные элементы сортируются, соединяются запятой и печатаются.
7
27.01.2020, 21:07

Теги

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