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