Удалите дублирующиеся поля в данном столбце

Использовать --color=always.

grep обнаруживает, если произведенный к каналу (или файл). Вы больше всего никогда не хотите цветов, когда произведенный должен зарегистрировать – поскольку это - escape-последовательности для терминала. Обычно:

foo ^[[01;31m^[[Kbar^[[m^[[K

от, например:

grep pattern file > result

Переопределять использование --color=always.

grep --color=always pattern file | ...

Пример:

Наличие файла:

ID=111;Year=2013;foo=bar
ID=222;Year=2013;foo=baz

Затем

grep --color=always ID file | grep --color=always 2013 | grep foo

окрасил бы ID, 2013 и foo.

grep --color=always ID file | grep 2013 | grep foo

окрасил бы ID и foo, но нет 2013.

1Important: также необходимо помнить, что добавленная помеха от цветов передается для следующего управления в цепочке. После того как идентификатор окрашен, Вы не можете (легко), соответствие, например. ID=111.


На немного вызывают, можно было бы, возможно, хотеть терминал, раскрашивает файл. Попробуйте, например.

 grep --color=always foo file > result
 cat result

Хотя получающийся файл имел бы очень ограниченную мобильность.


Окраска себя является также расширением.


Как упомянуто хорошим @slm, Вы могли добавить:

export GREP_OPTIONS="--color=always"

к Вашему .bashrc и т.д., но не делайте, если Вы по некоторым причинам действительно не понимаете последствий и все еще хотите сделать это. Это во многих отношениях повредилось бы grep из-за того, что упомянутый выше 1.

Добавьте alias если Вы часто используете его.

 alias cgrep='grep --color=always'

GREP_OPTIONS и --color выберите три варианта: never, auto и always. Первые два должны быть единственными, для которых рассматривают GREP_OPTIONS.

Вы могли также проверить GREP_COLORS в man страницы или в гну grep.

5
21.08.2014, 12:48
3 ответа
perl -lpe 's/\s\K\S+/join ",", grep {!$seen{$_}++} split ",", $&/e'

Вы можете запустить это так:

$ perl -lpe 's/\s\K\S+/join ",", grep {!$seen{$_}++} split ",", $&/e' afile 
A    1,2,3,4
B    5,6
C    15

Как это работает

Первый вызов perl с помощью -lpe выполняет следующие 3 действия .

  • -l [восьмеричный] разрешить обработку окончания строки, указывает признак конца строки
  • -p принять цикл как -n, но также вывести строку, как sed
  • -e program одна строка of program (разрешено несколько -e, опустить файл программы)

По сути, это принимает файл, удаляет символы новой строки, работает со строкой, а затем прикрепляет к ней символ новой строки, когда это делается. Таким образом, он просто просматривает файл и выполняет наш код Perl для каждого по очереди.

Что касается фактического кода Perl:

  • \ s означает символ пробела (пять символов [\ f \ n \ r \ t] и \ v ] в новых версиях perl , например [[: space:]] ).
  • \ K Сохраните содержимое слева от \ K, не включайте его в $ &
  • \ S + один или несколько символов, не входящих в набор [\ f \ n \ r \ t \ v]

Соединение ",", будет брать результаты и повторно объединять каждое поле так, чтобы оно было разделено запятой.

Разделение ",", $ & возьмет совпадения, найденные с помощью \ S + , и разделит их только на поля без запятой.

grep {! $ Seen {$ _} ++} возьмет номер каждого поля, добавит его к хешу, $ visible {} , где номер каждого поля - $ _ по мере прохождения каждого из них. Каждый раз, когда номер поля "виден", он подсчитывается с помощью оператора ++ , $ seen {$ _} ++ .

grep {! $ Seen {$ _} ++} вернет значение поля, если оно было показано только один раз.

Изменено, чтобы увидеть, что происходит

Если вы используете эту модифицированную мерзость, вы можете видеть, что происходит, когда этот Perl one liner перемещается по строкам файла.

$ perl -lpe 's/\s\K\S+/join ",", grep {!$seen{$_}++} split ",", $&/e; @a=keys %seen; @b=values %seen; print "keys: @a | vals: @b"' afile 
keys: 4 1 3 2 | vals: 1 1 1 1
A    1,2,3,4
keys: 6 4 1 3 2 5 | vals: 1 2 1 2 1 1
B    5,6
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1
C    15

Здесь показано содержимое $ seen {} в конце обработки строки из файла. Возьмем вторую строку файла.

B    4,5,6,3

И вот что моя модифицированная версия показывает эту строку как:

keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1

Это говорит о том, что мы видели поле № 6 (1 раз), поле № 4 (2 раза) и т. Д. И поле № 5 (1 время). Поэтому, когда grep {...} возвращает результаты, он будет возвращать результаты только из этого массива, если он присутствует в этой строке (4,5,6,3)и если мы видели это только 1 раз (6,1,15,5). Пересечение этих двух списков составляет (5,6), и это то, что возвращает grep .

Ссылки

7
27.01.2020, 20:32

С awk это достаточно просто, используя массив , split и обычный цикл :

{
    split($2, elements, ",")
    out = ""
    for (i in elements) {
        el = elements[i]
        if (!(el in used)) {
            out = out el ","
        }
        used[el] = 1
    }
    sub(/,$/, "", out)
    $2 = out
}
1

Для каждого В строке мы разделяем второй столбец запятыми и сохраняем биты в массив elements . Затем мы создаем новое значение для этого столбца с помощью цикла, проверяя, видели ли мы это значение раньше или нет. Мы сохраняем набор значений, которые мы уже видели в (ассоциативном) массиве used . Если el используется , мы видели это раньше и не должны помещать его в вывод; в противном случае он новый, и мы объединяем его с из и добавляем его к нашему набору видимых значений, чтобы мы больше не использовали его. Наконец, мы помещаем составленный список обратно во второй столбец. По сути, это подход, который вы бы применили на любом другом языке.

Поместите приведенный выше код в файл и запустите его с помощью awk -f или заключите его в одинарные кавычки в качестве аргумента командной строки.

4
27.01.2020, 20:32
{ 
    tr -cs '0-9ABC' '[\n*]' | 
    nl -w1 -s: |
    sort -t: -uk2,2 | sort -t: -k1,1n |
    sed 's/[^:]*://;/^[ABC]/!{H;$!d
        };x;y/\n/,/;s/,/\t/'

} <<\FILE
A       1,2,3,4
B       4,5,6,3
C       2,15
FILE

В основном это просто требует некоторых мер, чтобы гарантировать, что данные могут быть пропущены через sort -u и по-прежнему возвращаться снова в относительно той же форме, в которой они были выведены.

Сначала tr преобразует любой входной байт, который не является цифрой или ABC , в новую строку и сжимает любые повторы. Таким образом, каждое поле имеет свою строку. Затем

nl нумерует каждую строку во входных данных. Его вывод выглядит так:

1:A
2:1
3:2

... и так далее.

Далее данные сортируются ред - дважды. Первая сортировка удаляет все повторяющиеся поля - она ​​работает только со своим вторым полем данных в строке и разделяет эти поля с помощью : . Вторая sort восстанавливает исходный порядок - нумерованный порядок nl - на этот раз с помощью sort в первом поле.

Последний sed снова собирает все вместе. Он собирает свои входные данные, удаляя все вставки nl , а e x изменяет свои буферы удержания и шаблона для строк ABC и $ последний. На каждом из них он y преобразует все \ n ewlines в , запятые и последний заменяет на первый из них на строку.

А результаты?

ВЫВОД

A       1,2,3,4
B       5,6
C       15

И это, друзья, делает Unix замечательной.

И, поскольку мне было любопытно, вот только sed :

sed 's/\t\(.*\)/,\1,/;H;$!d;x;:t
     s/,\([^,]*,\)\(.*,\)\1/,\1\2/;tt
     s/,\(\n.\),/\1\t/g;s/,\(.*\),/\t\1/'
' <<\FILE
A       1,2,3,4
B       4,5,6,3
C       2,15
FILE

Первая и третья строки похожи на Prep / cleanup. Первый переносит весь файл в пространство шаблонов и гарантирует, что каждое поле разделено запятыми, поэтому первая строка, например:

A,1,2,3,4,

выглядит так после завершения.

Во второй строке выполняется вся работа. На самом деле это рекурсивная функция замены - она ​​постоянно заменяет любое поле с разделителями-запятыми, которое может быть сопоставлено в другом месте, только самим собой, пока больше не будет найдено. Это функция команды t est.

Третья строка, как я уже сказал, просто все очищает. Он возвращает запятые, вкладки и т. Д., И конечный результат:

ВЫВОД

A       1,2,3,4
B       5,6
C       15

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

5
27.01.2020, 20:32

Теги

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