Распечатать, если для одного и того же 1-го поля во всех строках есть одно значение 2-го поля

Вы можете удалить все разрешения для группы nosu, используя ACL.

setfacl -m g:nosu:--- /usr/bin/pkexec

После настройки ACL пользователи, не входящие в группу nosu, по-прежнему обычно используют pkexec .

1
01.03.2017, 00:45
5 ответов

Вот один способ с awk :

awk 'NR==FNR{if (x[$1]++){if ($2!=t){z[$1]++}} else {t=$2};
next}!($1 in z)' infile infile

Этот файл обрабатывается дважды - на первом проходе проверяется наличие разных значений второго поле, когда 1-е поле имеет то же значение - если это так, он использует $ 1 в качестве индекса массива, тогда на 2-м проходе он печатает, только если 1-е поле не является индексом массива.
Или, если вы не против использовать sort с awk :

sort -u infile | awk 'NR==FNR{seen[$1]++;next}seen[$1]==1' - infile

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

2
27.01.2020, 23:14
sed '
    /\n/D
    :1
    $! {
        N
        /^\(\S\+\s\).*\n\1[^\n]\+$/ b1
    }
    /^\([^\n]\+\n\)\(\1\)\+[^\n]\+$/! D
    h
    s/\n[^\n]\+$//p
    g
    s/.*\n/\n/
    D
    ' file
0
27.01.2020, 23:14
sed -e '
   # this is a do-while loop which collects lines till the time the first
   # field remains the same. We break out of the loop when we see
   # a line whose 1st field != prev lines 1st field **OR** we hit the eof.
  :a
     $bb
     N
  /^\(\S\+\) .\(\n\1 .\)*$/ba

  :b

  # all equal
  # **Action:** Print and quit

  /^\(\S\+ .\)\(\n\1\)*$/q


  # all same 1st fld, but lines unequal, otw would have matched above
  # **Action:** Drop the whole block as its uninteresting

  /^\(\S\+\) .\(\n\1 .\)*$/d


  # all equal, and trailing line part of next line
  # **Action:** Display upto the last newline and restart 
  # with the trailing portion

  /^\(\(\S\+ .\)\(\n\2\)*\)\n[^\n]*$/{
     h
     s//\1/p   
     g
  }


  # of same 1st fld but some lines unequal, and trailing portion has
  # next line
  # **Action:** strip till the last newline, and restart over with the
  # trailing part

  s/.*\(\n\)/\1/
  D
' yourfile

Это очень интересная проблема для решения "Sed". Однако то, чего мне не хватает, - это несколько лучший или, лучше сказать, более широкий набор входных данных, предоставляемых OT на SE. Я предлагаю разместить тесты реалистичного масштаба и разнообразия на сайте htttp: / pastebin, который очень полезен для таких вещей.

2
27.01.2020, 23:14

Для записи, еще одна альтернатива с AWK без необходимости двойного чтения файла. Кажется, работает даже с несортированным файлом или даже с записями, найденными в файле только один раз.

$ awk '( a[$1] && (($2!=a[$1]) || ($1 in bad)) ) {bad[$1]++}; \
{a[$1]=$2;f1[FNR]=$1;f2[FNR]=$2}; \
END {for (i in f1) {if (!(f1[i] in bad)) print i,f1[i],f2[i]}}' ./tmp/file12


1 A T
2 A T
3 A T
12 C F
13 C F
21 E F

Где file12 выглядит так:

$ cat -n ./tmp/file12
 1  A T
 2  A T
 3  A T
 4  B T
 5  B T
 6  B F
 7  B F
 8  B T
 9  B F
10  B F
11  B F
12  C F
13  C F
14  D F
15  D T
16  D F
17  D F
18  D F
19  D F
20  D F
21  E F

Некоторые пояснения:

( a[$1] && (($2!=a[$1]) || ($1 in bad)) ) {bad[$1]++};
# The first time value $1 is checked,a[$1] will return null/0 since a[$1]
# has never been assigned. Thus a[$1] will be evaluated as false by
# condition check and further condition check and record bad marking will be skipped.
# The second time (second line) a[$1] will have a value and will be evaluated as true . 
# Then we check if $2 is equal to previous a[$1]=$2. If it is equal all ok.  
# Otherwise if current $2 <> previous a[$1] $2value, mark this record as bad.
# Finally there is a last check if record has been already been marked as bad.

{a[$1]=$2;f1[FNR]=$1;f2[FNR]=$2};     #some array delcaration

END {for (i in f1) {if (!(f1[i] in bad)) print i,f1[i],f2[i]}}' ./tmp/file12 
# Printing the lines of file that does not belong in bad boys.
1
27.01.2020, 23:14

Если у вас есть доступ к кэшу данных GNU , вы можете свернуть данные следующим образом:

datamash -W groupby 1 countunique 2 collapse 2 < file 
A   1   T,T,T
B   2   T,T,F
C   1   F,F
D   2   F,T,F

Это упрощает постобработку с помощью awk , например:

datamash -W groupby 1 countunique 2 collapse 2 < file | 
  awk '$2==1 {n = split($3,a,","); for (i=1;i<=n;i++) print $1, a[i]}'
A T
A T
A T
C F
C F
1
27.01.2020, 23:14

Теги

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