Сценарий для сравнения 2 входных параметров и шоу совместно использовал букву (буквы)

Программа login наборы MAIL переменная окружения, когда Вы входите в виртуальную консоль Linux.

От login(1) страница справочника:

Значение за $HOME, $USER, $SHELL, $PATH, $LOGNAME и $MAIL установлено согласно соответствующим полям во вводе пароля.

login программа, используемая для запуска сессии, когда Вы входите в виртуальную консоль Linux. Это предлагает Вам имя пользователя и пароль, устанавливает некоторые основные переменные окружения и запускает оболочку.

Если Вы используете графического менеджера по входу в систему (например, один предоставленный с Gnome или KDE) вместо login, MAIL переменная окружения не может быть установлена.

Bash обычно только дает почтовые уведомления, когда он используется в качестве оболочки входа в систему. Даже если MAIL переменная окружения установлена, нормальный интерактивный экземпляр bash в xterm или konsole не отобразит почтовое уведомление.

Можно работать bash с -l отметьте, чтобы вынудить это вести себя как оболочка входа в систему. Можно передать xterm -ls флаг, чтобы заставить его запустить Вашу оболочку как оболочку входа в систему.

4
01.10.2014, 23:31
3 ответа

Если вы можете полагаться на встроенные регулярные выражения Bash (а именно на оператор =~) и переменные массива, вы можете использовать нечто подобное:

#!/bin/bash
W1=( $( echo "$1" | sed "s/./\n&/g" | sort -u ) )
W2="$2"
set ${W1[*]}

while [[ ! -z "$1" ]]; do
    if [[ "$W2" =~ "$1" ]]; then
        printf "$1 "
    fi
    shift
done
printf "\n"

В первой строке создается массив, который содержит каждый символ, содержащийся в $1. Затем сохраняется $2, а затем позиционные параметры устанавливаются на значения элементов $W1. Затем каждый символ (теперь позиционный параметр) сопоставляется с сохраненным вторым словом и, если совпадение найдено, выводится. Наконец, позиционные параметры сдвигаются таким образом, что цикл продолжается со следующим символом.

Концепции, которые можно увидеть здесь: работа с массивом, захват вывода команды в переменную, изменение позиционных аргументов, цикл и условный оператор.

Если вы хотите сделать это просто, вы можете рассмотреть, например, эту (на самом деле это разделение на один лайнер для большей читабельности):

#!/bin/bash
printf "$1" \
    | sed "s/./\n&/g" | sort -u \
    | grep -F "$( printf "$2" | sed 's/./&\n/g' | sort -u )"

Сортировка sed | сортирует -u комбо просто разбивает слова на один уникальный символ в форме строки. grep -F рассматривает параметр (здесь разбитое второе слово) как фиксированные строки, которые должны быть сопоставлены во входных данных, и таким образом пытается сопоставить каждый символ в $1 с каждым символом в $2. В реальных ситуациях Вы, вероятно, удалите вторую сортировку | uniq, так как "слова" обычно довольно короткие, и любой прирост производительности будет уничтожен путем порождения двух дополнительных процессов. Однако, так как $2 становится больше (сотни или тысячи строк), Вы определенно хотите сделать любую возможную оптимизацию.

Вы также можете заменить команду sed на fold -w 1, которая делает почти то же самое (она короче для набора, но команда sed s - это нож швейцарской армии для обработки текста).

5
27.01.2020, 20:47

Ниже приводится простой подход, который выполняет итерацию по первой строке и проверяет, присутствует ли каждый символ во второй строке. Если символ присутствует, он напечатает его на консоли.

str1=$1;
i=0
while [ $i -ne ${#str1} ]
 do
 c=${str1:$i:1}
 if [[ $2 == *$c* ]]
  then
   echo $c
 fi
 ((i++))
done
4
27.01.2020, 20:47

Если вам нравятся маленькие одиночные ссылки, и вы не против пользоваться общими инструментами из GNU coreutils, то вы можете сделать что-нибудь вроде этого:

comm -12 <( fold -w1 <<< "$1" | sort -u ) <( fold -w1 <<< "$2" | sort -u )

Если вас не волнует регистр букв, вы можете поменять $1 и $2 на ${1,,} и ${2,,} соответственно.

Помимо утилит comm, fold и sort , в них используются <( ) командные substiutions и <<< here-strings.


В качестве альтернативы, если вы хотите получить чистый bash-ответ (без кореша) и хотите получить больше возможностей для работы с различными bash-функциями, вот еще:

declare -A arr
for (( i=0; i<${#1}; i++ )); do
    (( arr[${1:i:1}] |= 1 ))
done
for (( i=0; i<${#2}; i++ )); do
    (( arr[${2:i:1}] |= 2 ))
done
for i in ${!arr[@]}; do
    if (( ${arr[$i]} == 3 )); then
        echo $i
    fi
done

В этом случае используется ассоциативный массив bash , поэтому требуется версия 4 или более поздняя.

Он также использует (( )) арифметические расширения с битовой арифметикой.

Оно работает через символы первой строки и использует каждый из них как индекс в ассоциативном массиве. Элемент, соответствующий этому индексу, имеет значение ORed с 1 (или имеет свой бит 0).

То же самое происходит и со второй строкой, за исключением того, что элемент имеет значение 2 (или имеет свой бит 1).

Затем мы проходим по массиву в поисках элементов, имеющих биты 0 и 1 (т.е. равные 3), и выводим индекс (который является общей буквой).

3
27.01.2020, 20:47

Теги

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