Grep для рисунка в начале или в середине линии

Начну с того, что я думаю, что эта проблема немного менее невинна, чем кажется.

Что мне нужно сделать: проверьте папку в переменной среды PATH. Это может быть в начале или где-то после. Мне просто нужно проверить, что эта папка есть.

  • Безопасны ли бесплатные учетные записи?
  • Как написать сценарий оболочки перезапустить apache, если `сервер достиг MaxClients`
  • Создание пустого файла с именем переменной в скрипте
  • Почему цикл while пропускает и читает только первую строку?
  • Создание сценария оболочки, который анализирует и перенаправляет число в следующую команду?
  • ожидание сети в сценарии bash
  • Пример моей проблемы – давайте использовать /opt/gnome .


    SCENARIO 1: папка не находится в начале PATH

     # echo "$PATH" /sbin:/usr/sbin:/opt/gnome:/var/opt/gnome # echo "$PATH" | grep ":/opt/gnome" /sbin:/usr/sbin:/opt/gnome:/var/opt/gnome 

    Обратите внимание, что grep должен быть достаточно конкретным, чтобы он не ломал /var/opt/gnome . Отсюда и двоеточие.


    SCENARIO 2: папка находится в начале PATH.

     # echo "$PATH" /opt/gnome:/sbin:/usr/sbin:/var/opt/gnome # echo "$PATH" | grep "^/opt/gnome" /opt/gnome:/sbin:/usr/sbin:/var/opt/gnome 

    Это моя проблема – мне нужно найти двоеточие или начало строки с этой папкой. То, что я хотел бы сделать, это одно из этих двух выражений:

     # echo $PATH | grep "[^:]/opt/gnome" # echo $PATH | grep "[:^]/opt/gnome" 

    НО [^ и [: имеют свои значения. Поэтому две приведенные выше команды не работают.

    Есть ли способ, который я могу использовать для этих двух сценариев в одной команде?

  • Описание необычного пути
  • Работает в командной строке, но не в сценарии оболочки
  • Если «bash <file>» работает, почему «source <file>» выдает ошибку?
  • Как выполнить как зарегистрированный пользователь в скрипте sudo (OSX)?
  • Значение следующих команд Linux
  • KSH - если / then / else против двойных усилителей (&&) и двойных труб (||)
  • 8 Solutions collect form web for “Grep для рисунка в начале или в середине линии”

    Если вы проверяете содержимое PATH среды PATH , в отличие от поиска чего-либо в файле, grep является неправильным инструментом. Это проще (и быстрее и, возможно, более читаемо) сделать это в оболочке.

    В bash, ksh и zsh:

     if [[ :$PATH: = *:/opt/gnome:* ]]; then : # already there else PATH=$PATH:/opt/gnome fi 

    Портабельно:

     case :$PATH: in *:/opt/gnome:*) :;; # already there *) PATH=$PATH:/opt/gnome;; esac 

    Обратите внимание на использование :$PATH: вместо $PATH ; таким образом, компонент всегда окружен двоеточиями в строке поиска, даже если он был в начале или конце $PATH .

    Если вы просматриваете строку файла, вы можете использовать расширенное регулярное выражение (то есть требующее grep -E ) (^|:)/opt/gnome($|:) для соответствия /opt/gnome но только если это либо в начале строки, либо после двоеточия, и только в том случае, если она находится либо в конце строки, либо после нее.

    Вы можете использовать расширенные регулярные выражения, просто используя grep -E

    Вы должны соответствовать началу и концу пути, который вы пытаетесь найти, если хотите избежать ложных срабатываний.

    Соответствует экземпляру в начале:

     $ TEST=/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome $ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)" /opt/gnome:/sbin:/usr/sbin:/var/opt/gnome 

    Также совпадает с экземпляром в середине:

     $ TEST=/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome $ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)" /sbin:/usr/sbin:/opt/gnome:/var/opt/gnome 

    Избегайте ложных срабатываний:

     $ TEST="/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta" $ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)" 

    Нет совпадений.

    Компактный и элегантный. Протестировано на Debian 7.

    Надеюсь, поможет.

    Если вы не согласитесь на grep , вы можете использовать awk и разделить записи на :

     awk 'BEGIN {RS=":"} /^\/opt\/gnome$/' 

    Вы также можете использовать

    echo "$PATH" | tr ':' '\n' | grep -x "/opt/gnome"

    который разбивает переменную пути на отдельные строки (по одному на каждый путь), поэтому grep -x может искать точные результаты. Это, конечно, является недостатком того, что для tr требуется дополнительный процесс. И это не будет работать, если имя папки в PATH содержит символы новой строки.

    Я не знаю, достаточно ли для ответа, но

     grep -w "/opt/gnome" 

    удовлетворит ваши потребности.

     echo '/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome' | grep -w "/opt/gnome" -o /opt/gnome echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep -w "/opt/gnome" -o /opt/gnome 

    но

     echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep "/opt/gnome" -o /opt/gnome /opt/gnome 

    Чтобы выбрать /opt/gnome окруженный символами не-слова (новые строки, : , / и т. Д.), Попробуйте следующее:

     grep '\B/opt/gnome' 

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

    С основным регулярным выражением – и так с grep – у вас всегда есть два надежных якоря – голова и хвост линии. Вы можете привязать соответствие к обоим из них независимо от его местоположения на линии, например:

     grep '^\(ignore case, delimiter\)*match\(delimiter, ignore case\)*$' 

    grep будет соответствовать grep строки как много вхождений подвыражений \(grouped\) как это должно привести к следующему вашему разделителю, а затем вашему явному совпадению и от хвоста вашего совпадения до хвоста строки таким же образом , Если явное совпадение явно не согласовано, оно не будет выполнено и ничего не напечатает.

    И так вы можете сделать, например:

     grep '^\(.*:\)*/opt/gnome\(:.*\)*$' 

    Посмотреть на себя:

     grep '^\(.*:\)*/opt/gnome\(:.*\)*$ ' <<\INPUT /opt/gnome-beta /opt/gnome /home/bob/opt/gnome :/opt/gnome: /home/bob/opt/gnome:/opt/gnome:/opt/gnome-beta /opt-gnome-beta /opt/gnomenot::::/opt/gnome INPUT 

    ВЫВОД

     /opt/gnome :/opt/gnome: /home/bob/opt/gnome:/opt/gnome:/opt/gnome-beta /opt/gnomenot::::/opt/gnome 

    вы заметили краевой кейс … вы могли бы избежать этого, заставив появление: в начале строки:

      echo ":$PATH" | grep ":/opt/gnome" 

    или если путь является точным, добавьте также один в конец, чтобы убедиться, что он ограничен:

      echo ":${PATH}:" | grep ":/opt/gnome:" 
    Linux и Unix - лучшая ОС в мире.