2つの入力パラメータを比較して共有文字を表示するスクリプト

2つの入力パラメータを比較して共有文字を表示するスクリプト

私はユーザーに2つの別々の単語を入力させ、結果に2つの単語がどの文字を共有するかを示すスクリプトを作成しています。たとえば、./share Cat Rat - 共有文字「a」と「t」を返します。私の考えは$ 1と$ 2を繰り返すことですが、その後はどこに行くのかわかりません。私は今スクリプティングとUNIXを学び始めました。どうぞよろしくお願いします!

#!/bin/sh

echo "$1"|while read line

答え1

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要素の値に設定します。その後、各文字(現在の位置引数)は、2番目の保存された単語と一致し、一致するものがあれば印刷されます。最後に、位置パラメータが移動され、ループが次の文字に続きます。

ここで見ることができる概念は、配列の使用、コマンド出力を変数としてキャプチャ、位置引数の変更、ループ、および条件文です。

これを簡単にするには、次の点を考慮することをお勧めします(実際には読みやすくするために1行に分割します)。

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

これらのsed | sort -u組み合わせは、単に単語を1行に1つの一意の文字に分割します。grep -F引数(ここでは分割秒の単語)を入力で一致させる固定文字列として扱うので、 のすべての文字を のすべての文字$1と一致させようとします$2。実際の状況では、sort | uniq「単語」は通常非常に短く、2つの追加プロセスを作成するとパフォーマンスの向上が中断されるため、2番目の組み合わせを排除できます。ただし、$2規模が大きくなったら(数百行または数千行)、すべての可能な最適化を実行したいと思います。

ほぼ同じタスクを実行するsedwhichコマンドを置き換えることもできます(入力に時間がかかりませんが、そのコマンドはテキスト処理のスイス軍用ナイフと同じです)。fold -w 1seds

答え2

以下は、最初の文字列を繰り返し、各文字が2番目の文字列にあることを確認し、文字がある場合はその文字をコンソールに印刷する簡単な方法です。

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

答え3

ファンキーな短いジョークが好きで、GNU coreutilsの一般的なツールにアクセスできる場合は、次のことができます。

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

大文字と小文字を区別しない場合は、and$1$2andを別々に切り替えることができます。${1,,}${2,,}

しかもcommfoldそしてsortユーティリティは以下を使用します。<( ) コマンドの置き換えそして<<< ここにある文字列


あるいは、純粋なbashの答え(coreutilsなし)が欲しいので、さまざまな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以降が必要です。

それも使用します(( )) 算術拡張そしてビットごとの算術。

最初の文字列の文字を繰り返し、各文字を連想配列のインデックスとして使用します。このインデックスに対応する要素は1とORに関連付けられています(またはビット0が設定されています)。

要素が2とORで連結されていること(またはビット1が設定されている)を除いて、2番目の文字列に対して同じことが行われます。

次に、ビット0と1が設定された(つまり3に等しい)要素を見つける配列を繰り返し、インデックス(共通文字)を出力します。

関連情報