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요소의 값으로 설정합니다. 그런 다음 각 문자(현재 위치 인수)는 두 번째 저장된 단어와 일치하고 일치하는 항목이 있으면 인쇄됩니다. 마지막으로 위치 매개변수가 이동되어 루프가 다음 문자로 계속됩니다.

여기서 볼 수 있는 개념은 배열 사용, 명령 출력을 변수로 캡처, 위치 인수 변경, 루프 및 조건문입니다.

이 작업을 간단하게 수행하려면 다음을 고려하는 것이 좋습니다(실제로는 가독성을 높이기 위해 한 줄로 분할합니다).

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

이러한 sed | sort -u조합은 단순히 단어를 한 줄에 하나의 고유한 문자로 분리합니다. grep -F인수(여기서는 분할 초 단어)를 입력에서 일치시킬 고정 문자열로 처리하므로 의 $1모든 문자를 의 모든 문자와 일치시키려고 시도합니다 $2. 실제 상황에서는 sort | uniq"단어"가 일반적으로 매우 짧고 두 개의 추가 프로세스를 생성하면 성능 향상이 중단되므로 두 번째 조합을 제거할 수 있습니다. 그러나 $2규모가 커지면(수백 또는 수천 행) 가능한 모든 최적화를 수행하고 싶을 것입니다.

거의 동일한 작업을 수행하는 sedwhich 명령을 대체 할 수도 있습니다 (입력하는 데 시간이 덜 걸리지만 해당 명령은 텍스트 처리의 스위스 군용 칼과 같습니다).fold -w 1seds

답변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,,}

게다가comm,fold그리고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이 설정되어 있음)을 제외하고 두 번째 문자열에 대해 동일한 작업이 수행됩니다.

그런 다음 비트 0과 1이 설정된(즉, 3과 같음) 요소를 찾는 배열을 반복하고 인덱스(공통 문자)를 출력합니다.

관련 정보