Как проверить, содержит ли строка подстроку, состоящую из тире или ясеня?

mosh использует среду локали, поддерживаемую ssh. Хотя mosh, очевидно, не имеет verbose- или debug-опций, вы можете указать ему, какую ssh команду использовать при подключении, и, добавив опцию -vvv, заставить ssh показать, какие переменные локали он отправляет.

Например, начиная с

mosh -ssh='ssh -vvv' root@server

вы можете увидеть

debug1: Sending env LC_ALL = C  
debug2: channel 0: request env confirm 0

для POSIX, и

debug1: Sending env LC_CTYPE = en_US.UTF-8
debug2: channel 0: request env confirm 0

которые показывают, что сервер подтверждает переменные, которые используются. Удаленный sshd может игнорировать некоторые из вашего окружения в зависимости от настройки AcceptEnv в конфигурации для sshd - или настроек SendEnv вашего пользователя (в конфигурации ssh).

Не все серверы принимают ваши переменные локали через ssh.

Даже если конфигурация настроена разрешительно, все равно возможно (особенно если вы подключаетесь к пользователю root), что кто-то решил, что локаль для этого пользователя должна быть POSIX. Для root это имеет определенный смысл, поскольку при копировании select/paste у вас будет меньше проблем.

Например, некоторые системы используют /etc/profile.d/lang.sh для установки локали для интерактивного использования. Этот скрипт отличается в разных системах, и это второе место (после конфигураций ssh/sshd), на которое следует обратить внимание при поиске объяснения, почему информация о локали не передается удаленной системе. В Red Hat (CentOS) скрипт пытается получить информацию из системной и домашней конфигурации, например,

if [ -n "$LANG" ]; then
    saved_lang="$LANG"
    [ -f "$HOME/.i18n" ] && . "$HOME/.i18n" && sourced=1
    LANG="$saved_lang"
    unset saved_lang
else
    for langfile in /etc/locale.conf "$HOME/.i18n" ; do
        [ -f $langfile ] && . $langfile && sourced=1
    done
fi

SuSE отличается, делая предположения о ssh и gdm до чтения по сути тех же файлов:

#
# lang.sh:      Set interactive language environment
#
# Used configuration files:
#
#     /etc/sysconfig/language
#     $HOME/.i18n
#

#
# Already done by the remote SSH side
#
test -z "$SSH_SENDS_LOCALE" || return

#
# Already done by the GDM
#
test -z "$GDM_LANG" || return

Для ваших конкретных серверов (версия не указана) скрипт может отличаться от одного выпуска к другому. Мои серверы Debian не имеют такого файла - и полагаются на системную локаль по умолчанию и gdm (которые могут отличаться) для установки интерактивной локали. Ваше ssh-соединение может использовать другое значение системной локали, чем интерактивный сеанс с использованием X (через gdm). В этом случае нужно исправить системную локаль (см. Locale в Debian wiki).

3
27.11.2016, 02:28
3 ответа

bash поддерживает это изначально,

$ string1="abcmoocow"
$ string2="moo"
$ if [[ $string1 == *$string2* ]]; then echo "Match"; else echo "No Match"; fi
Match
$ string1="abccrowcow"
$ if [[ $string1 == *$string2* ]]; then echo "Match"; else echo "No Match"; fi
No Match

также для исправления вашего примера; change;

if $(echo $1 | grep -c $2) ; then

превратиться в:

if [ -n "$(echo $1 | grep -c $2)" ]; then

(проверяет, возвращает ли grep какие-либо данные)

также обратите внимание, что также можно работать с кодом выхода;

$ echo bob | grep "o" &>/dev/null; echo $?
0
$ echo bob | grep "z" &>/dev/null; echo $?
1
1
27.01.2020, 21:11

В оболочке Bourne есть конструкция для этого. Это то же самое, что и в современном sh (который больше похож на то, что вы используете, оболочка Bourne не поддерживает $ (...) ; если это была оболочка Bourne , вы получите другую ошибку):

case $1 in
  *"$2"*) printf '"%s" is in "%s"\n' "$2" "$1"
esac

Если вы хотите использовать grep , это будет:

if printf '%s\n' "$1" | grep -Fqe "$2"; then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi

или

if grep -Fqe "$2" << EOF
$1
EOF
then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi

Но это будет работать правильно, только если $ 2 не содержал символа новой строки.

В любом случае, вам нужно заключить в кавычки большую часть этого расширения параметров. Единственное место, где он не нужен, - это случай $ 1 выше, но даже тогда случай «1 доллар» не повредит.

Несколько примечаний к вашему коду:

  1. Вы не можете использовать echo для произвольных строк .Здесь, в зависимости от реализации echo , он не сработает для значений $ 1 , например -n или foo \ bar .
  2. Оставление расширения параметра без кавычек имеет особое значение в оболочках . Вы не хотите этого делать. Попробуйте, например, grep -c $ 2 со значением $ 2 , например * или root / etc / passwd .
  3. grep без -F предназначен для сопоставления регулярных выражений. Вам понадобится -F для поиска по фиксированной строке (подстроке) (раньше было с fgrep ), но опять же, если $ 2 содержит несколько строк, это говорит grep -F для поиска любого содержимого этих строк во входных данных ( grep -F $ 'a \ nb' будет искать a ] или b , а не $ 'a \ nb' строка).
  4. В grep -c $ 2 содержимое $ 2 будет использоваться в качестве опции, если оно начинается с - . Чтобы этого избежать, вы хотите grep -c -e "$ 2" или grep -c - "$ 2" .
  5. Вы хотите использовать статус выхода, а не стандартный вывод для сообщения логических условий. В сценариях с exit ( exit 0 для истины, exit 1 (или любое ненулевое число, но избегайте значений больше 120) для false). Для функций используйте вместо этого return . Хотя и скрипты, и функции вернутся со статусом последней команды запуска.
  6. $ (cmd) расширяет до вывода cmd (и подвергается здесь split + glob из-за отсутствия кавычек снова) за вычетом завершающих символов новой строки. Таким образом, если cmd выводит 0 \ n , $ (cmd) расширяется до 0 . Итак, при запуске $ (cmd) пытается выполнить команду с именем 0 . Если вы хотите преобразовать вывод cmd в статус выхода (чтобы его можно было использовать как логическое), вам понадобится (exit «$ (cmd)») . Это запускает подоболочку, которая завершается с выводом cmd в качестве кода выхода).
  7. grep -c подсчитывает количество вхождений. Здесь вам не обязательно иметь полный счет, вам нужно только знать, найдено ли оно вообще (есть ли хотя бы одно совпадение).Для этого grep -q более эффективен, так как он прекращает поиск после того, как нашел его. Для старых реализаций grep , которые не поддерживают (стандартный) -q параметр, вы можете использовать fgrep -le "$ 2"> / dev / null . С -l , fgrep также останавливается при первом совпадении, но выводит имя файла (которое мы здесь отбрасываем, перенаправляя вывод на / dev / null ) .
7
27.01.2020, 21:11

Портативный (dash,bash,ksh и т. д. )скрипт, содержащий функцию:

#!/bin/sh

contains() {  if    [ "$1" ] &&            # Is there a source string.
                    [ "$2" ] &&            # Is there a substring.
                    [ -z "${1##*"$2"*}" ]; # Test substring in source.
              then  echo 0;                # Print a "0" for a match.
              else  echo 1;                # Print a "1" if no match.
              fi;
            }

contains "$1" "$2"

Где 0 означает "содержит" (истинное значение ).

, который будет проверяться как:

 $ contains "test a simple line" simpl
 1

 $ contains "One sentence" "No more"
 0
4
27.01.2020, 21:11

Теги

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