Автор Тема: Bash. Найти лишний элемент. [решено]  (Прочитано 1884 раз)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Есть n-ое количество записей, которые идут через цикл for:
for i in element1 element2 element5; do
...
done
Этот цикл вложен в другой цикл:
for j in elemen2 element5; do
   for i in element1 element2 element5; do
   ...
   done
done
Каким то образом мне нужно сравнить эти элементы между собой и найти те, которые встречаются только во вложенном цикле (в основном стало быть этого элемента нет). В данном случае это element1. Лишние элементы могут быть только во вложенном цикле, т.е. если какой-то элемент есть в основном цикле, то он точно есть во вложенном.
Цикл можно взять другой, это не имеет значения. Да даже можно не цикл использовать, мне просто из 2 наборов элементов нужно найти лишние элементы. Лишних элементов может быть несколько.
Подскажите как мне их обнаружить ?
У меня не получается...

Заранее спасибо.
« Последнее редактирование: 05.01.2013 18:16:59 от berkut_174 »
Сноси Винду, переходи на Линукс ! :)

Оффлайн Skull

  • Глобальный модератор
  • *****
  • Сообщений: 20 166
    • Домашняя страница
Re: Bash. Найти лишний элемент.
« Ответ #1 : 05.01.2013 16:28:40 »
Правильный юниксовый способ:
sort | uniq -u
Андрей Черепанов (cas@)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент.
« Ответ #2 : 05.01.2013 16:40:52 »
Правильный юниксовый способ:
sort | uniq -u
Не понял как мне это применить...
Сноси Винду, переходи на Линукс ! :)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент.
« Ответ #3 : 05.01.2013 16:45:52 »
map="chel mosc"
mask="`ls ~/1/back* | cut -f2 -d_ | cut -f1 -d-`"
for i in $mask; do
    for j in $map; do
    ...
    done
done
Мне нужно найти файлы которые не удовлетворяет условиям переменной map (не содержат в имени этих символов) и удалить его/их.
« Последнее редактирование: 05.01.2013 16:47:38 от berkut_174 »
Сноси Винду, переходи на Линукс ! :)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент.
« Ответ #4 : 05.01.2013 18:16:51 »
sort | uniq -u
Применил :)
Спасибо!

[решено]
Сноси Винду, переходи на Линукс ! :)

Оффлайн Skull

  • Глобальный модератор
  • *****
  • Сообщений: 20 166
    • Домашняя страница
Re: Bash. Найти лишний элемент.
« Ответ #5 : 05.01.2013 23:06:47 »
Есть несколько нюансов.
1. uniq -u (выводить только уникальные строки) сработает как положено только тогда, когда есть все файлы со всеми подстановками. Иначе будут выводится неиспользованные подстановки.
2. Для более точного получения пересечений используют join, но он требует двух входных файлов, что проблематично при обработке через конвейеры (pipe, |).
3. В данном случае, если нужно вывести файлы, удовлетворяющие тому или иному шаблону, воспользуйтесь egrep (grep с расширенным синтаксисом, который может принимать альтернативы) и параметром -v (показывающим файлы без вхождения).
Получается однострочник на Bash:
ls ~/1/back* | egrep -v '^[^_]*_(chel|mosc)-' | xargs rm -f
Андрей Черепанов (cas@)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент. [решено]
« Ответ #6 : 06.01.2013 11:08:02 »
ls ~/1/back* | egrep -v '^[^_]*_(chel|mosc)-' | xargs rm -f
Круто! Спасибо за консультацию :)
Только ещё один вопрос: у меня переменная такого видаmap="chel mosc kaz"Как мне её (переменную) впихнуть в эту строку, чтобы было через | ?
Сноси Винду, переходи на Линукс ! :)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент. [решено]
« Ответ #7 : 06.01.2013 11:33:25 »
Как мне её (переменную) впихнуть в эту строку, чтобы было через | ?
Вот так получилось:
ls ~/1/back* | egrep -v "^[^_]*_(`echo -n $map | sed 's/ /|/g'`)-" | xargs rm -f
« Последнее редактирование: 06.01.2013 11:38:59 от berkut_174 »
Сноси Винду, переходи на Линукс ! :)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент. [решено]
« Ответ #8 : 06.01.2013 12:19:17 »
Да что такое, опять проблема нарисовалась...
У меня в пути "_" есть, из-за этого удаляются все файлы в папке.
Как модифицировать команду ?
Если сделать так:ls ~/"1 2"/back* | egrep -v "[^$mask]*_(`echo -n $map | sed 's/ /|/g'`)-" | xargs rm -f Тогда вообще ничего не удаляется. Хотя есть убрать xargs файл правильно определяется.

PS. У меня пробел в пути ещё есть.
« Последнее редактирование: 06.01.2013 12:24:39 от berkut_174 »
Сноси Винду, переходи на Линукс ! :)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент. [решено]
« Ответ #9 : 06.01.2013 13:46:11 »
В мане нашел
find /tmp -name core -type f -print0 | xargs -0 /bin/rm -fа вот egrep не получается ещё прикрутить... не срабатывает тогда.
find /tmp -name $mask -type f -print0 | xargs -0 egrep -vi "[^$mask]*_(`echo -n $map | sed 's/ /|/g'`)-" | xargs -0 rm
Сноси Винду, переходи на Линукс ! :)

Оффлайн berkut_174

  • Мастер
  • ***
  • Сообщений: 7 152
Re: Bash. Найти лишний элемент. [решено]
« Ответ #10 : 06.01.2013 21:05:25 »
Решение:
-Q, --quote-name           заключать имя файла в кавычки
      --quoting-style=ТИП    использовать тип заключения в кавычки ТИП:
                             literal, shell, shell-always, c, escape
ls -Q ~/"1 2"/back* | egrep -v "[^$mask]*_(`echo -n $map | sed 's/ /|/g'`)-" | xargs rm -f
Сноси Винду, переходи на Линукс ! :)