Поиск повторяющихся блоков текста в файле с помощью сценария оболочки

Обычно я создаю следующий скрипт либо в /usr/local/bin, либо в $HOME/bin.

#!/bin/bash
HOSTNAME=`uname -n`
ARG=`echo $DISPLAY | sed -e "s/localhost/$HOSTNAME\/unix/"`
XAUTH=`/usr/bin/xauth -i -f ~/.Xauthority list ${ARG}`

echo "The following is used for graphical displays through ssh."
echo "Copy and paste the following commands AFTER you have \"su - [user]\""
echo "----------------  Copy below  ------------------------------------"
echo "DISPLAY=$DISPLAY;export DISPLAY"
echo "/usr/bin/xauth -bi add \\"
echo "${XAUTH}"
echo "----------------  Copy above  ------------------------------------"

Вы должны выполнить этот сценарий до, используя su или sudo. Став другим пользователем, вырежьте и вставьте вывод, как указано. Ваши программы X должны работать.

[bschuck@dhcp-10-100-11-138 ~]$ bin/xtunnel 
The following is used for graphical displays through ssh.
Copy and paste the following commands AFTER you have "su - [user]"
----------------  Copy below  ------------------------------------
DISPLAY=localhost:10.0;export DISPLAY
/usr/bin/xauth -bi add \
dhcp-10-100-11-138/unix:10  MIT-MAGIC-COOKIE-1 \
b64ace6b49bb1b49c59679a2db6411eb
----------------  Copy above  ------------------------------------
[bschuck@dhcp-10-100-11-138 ~]$ su - zippy
Password: 
[zippy@dhcp-10-100-11-138 ~]$ DISPLAY=localhost:10.0;export DISPLAY
[zippy@dhcp-10-100-11-138 ~]$ /usr/bin/xauth -bi add \
> dhcp-10-100-11-138/unix:10  MIT-MAGIC-COOKIE-1  
b64ace6b49bb1b49c59679a2db6411eb
[zippy@dhcp-10-100-11-138 ~]$ xclock &
[1] 6076
[zippy@dhcp-10-100-11-138 ~]$
0
29.06.2017, 09:21
3 ответа

Используйте

for i in `awk '/}/ {if (NR!=1) print "";next} \
                {printf "%s ",$0,"}"}END{print ""}' yt.txt \
        |awk '{print $1}'|sort|uniq \
    `; \
    do \
        awk '/}/ {if (NR!=1) print "";next} \
            {printf "%s ",$0,"}"}END{printf ""} \
            ' yt.txt \
         |grep "$i"|sed 's/ /\n/g'|grep -v "$i"|sort|uniq \
            |awk -v var="$i" ' NR==1 {printf var} {print $0} END {print "}"}'  \
    ;done \

Та же команда в 1 строке ниже (для копирования)

for i in `awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"}END{print ""}' yt.txt|awk '{print $1}'|sort|uniq` ; do awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"}END{printf ""}' yt.txt|grep "$i"|sed 's/ /\n/g'|grep -v "$i"|sort|uniq|awk -v var="$i" ' NR==1 {printf var} {print $0} END {print "}"}' ;done

Объяснение:

Часть forвернет вам уникальный заголовок блока (abcd/efgh/a.jar,lkmn/opqr/b.zip) и передать его в блок do. Часть doсначала будет grepвсе строки для каждого заголовка, которые также будут включать дубликаты. Затем он исключит заголовок и объединит все оставшиеся строки под этим блоком заголовков, а затем добавит заголовок в первую строку. И хардкод }в конце.

Пример

bash-4.2$ cat yt.txt
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
abcd/efgh/a.jar
{
cdef/ghij/b.class
d.class
}



bash-4.2$ for i in `awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"} \
> END{print ""}' yt.txt |awk '{print $1}'|sort|uniq` \
> ; do awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"}END{printf ""}' yt.txt \
>  |grep "$i"|sed 's/ /\n/g'|grep -v "$i"|sort|uniq \
> |awk -v var="$i" ' NR==1 {printf var} {print $0} END {print "}"}'\
> ;done
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
d.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
2
28.01.2020, 02:25

После того, как я увидел решение, использующее цикл forс awkи sort, и uniq, и grep, и sed, я попробовал решение с одним инструментом вместо шести:

sed ':a
  N;$!ba
  y/\n_/_\n/;s/^/_/
  :b
  s/\(_[^_]*_{\)\([^}]*\)\(_[^_}]*\)\(_[^}]*\)\(_}.*\)\1\([^}]*\)\3_/\1\2\3\4\5\1\6_/;tb
  :c
  s/\(_[^_]*_{\)\([^}]*\)_}\(.*\)\1\([^}]*\)_}/\1\2\4_}\3/;tc
  s/^_//
  y/\n_/_\n/' yourfile

выполняет свою работу, но я должен признать, что регулярные выражения легче писать, чем читать... (-;

1
28.01.2020, 02:25
perl -alF'/\n[}{]\n/' -0777ne '
   for ( 0.. $#F/2 ) {
      my $i = 2*$_;
      my($k,$v) = @F[$i,$i+1];
      if ( exists $h{$k} ) {
         $h{$k}.= join $\, grep { ! exists $seen{$k,$_} } split $\, $v;
      } else {
         push @k, $k;
         $seen{$k,$_}++ for split $\, $h{$k} = $v;
      }
   }
   print "$_\n{\n$h{$_}\n}" for @k;
' yourfile

Результаты

abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}

Работа

Входной файл обрабатывается, а затем разбивается на поля на основе разделителя полей, указанного в опции -F. Мы получим четное количество элементов в массиве @F. Затем четные номера используются как ключи хеша %h, в то время как их соответствие. значения берутся из следующего нечетного значения.

Хэш %hзаполняется путем разделения элементов с нечетными номерами на разделитель записей ($\ = \n ). В то же время мы помещаем ключ в массив @k, чтобы мы могли получить элементы хеша в том порядке, в котором они были обнаружены.

Все это время используются только те нечетные элементы, которые еще не видны.

0
28.01.2020, 02:25

Теги

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