본문 바로가기
리눅스 관련/shell scrtipt 쉘

bash shell 코드 문법 정리

by 알 수 없는 사용자 2022. 9. 28.

 

https://jybaek.tistory.com/477

 

[sh] "$*" 과 "$@"의 차이

흔히 $*와 $@를 구분 없이 많이 사용하고 있는데, 사실 약간은 다르다. 레퍼런스에 보면 아래와 같이 정의되어 있다. "$*" All the positional parameters (as a single word) * "$@" All the positional paramete..

jybaek.tistory.com

 

 

https://blog.gaerae.com/2015/01/bash-hello-world.html

 

Bash 입문자를 위한 핵심 요약 정리 (Shell Script)

 

blog.gaerae.com

 

 

 


 


bash argv 인자 설명

#!/bin/bash

#첫번째, 두번째, 세번째 인자
echo $0' '$1' '$2
echo "${0} ${1} ${2}"

#인자의 개수
echo "$#"

#모든 인자를 별도의 단어로
echo "$@"

# 모든 인자를 하나의 단어로
echo "$*"

 


변수명앞에 $ 를 붙여줘야 변수로 인정이 됨.

ex)

HOST_NAME="liam"

HOST_URL="172.19.138.161"

echo $HOST_NAME

echo $HOST_URL

또는 

PASSWORD="1234"

HOST_COMMAND="sshpass -p $PASSWORD ssh $HOST_NAME@$HOST_URL"

echo $HOST_COMMAND

이렇게 쓰면 됨.

 

$@           :  source ./bashfile.sh 변수1 변수2 변수3  : 리스트처럼 변수 1, 2, 3 이 담김  [1, 2, 3]

$*             :  source ./bashfile.sh 변수1 변수2 변수3  :  String처럼 변수1, 2, 3 이 담김    "1, 2, 3"

$?            :  가장 최근 명령어의 종료 상태 ( return 값 0 인경우 정상종료 ) 명령어 잘됬는지 확인용

$CMD      :  bash 쉘 명령어를 실행 할 수 있다. 예시 : $CMD mkdir test

 

bash -c ' ~~~~~~ '  일경우

A 명령어 && B 명령어 이런식으로 많이쓰는데

&& 는 명령어A가 성공하고 나서 명령어B 를 실행

& 는 명령어A를 실행하고 명령어B를 백그라운드로 실행 )

;  명령어A 실패여부와 관계없이 명령어B실행

||  는 &&처럼 순서대로 동작하지만, 명령어A가 성공시 명령어B는 실행하지 않는다.

|   는 &와 비슷해보이지만 다름. 명령어 A 와 명령어 B가 둘다 해당되는 조건을 수행한다. ( ls | grep *.sh )

     따라서 | 같은경우 명령어 실패에 대한 탈출구로써도 쓰임. ex) qq && echo 'aa' [실행X] , qq | true && echo 'aa' [실행O]

ex )  mkdir test3 && { cd test3; touch abc; echo 'success!!' } || echo 'There is no dir';

 

bash -c ONE LINE 한줄쓰기

result=$(find /usr/bin/ -name 'sshpass') && bash -c 'if [ -z $result ]; then echo "1111111111"; else echo $result; fi'

구조 : bash -c ' ~~ ' 에서 if문뒤에 ;   실행문뒤에 ; 를 써줘야한다.

 

아웃풋 저장하는 법

GMQTT_PATH=$(find / -name 'gmqtt')

사용할때 : $GMQTT_PATH

STR_A="asdf/asdas/asdsad/asdasd"

사용할때 : $STR_A

 


 

문자열 가공하는 방법

${변수이름:시작점}                      : 시작점부터 끝까지 가져옴
${변수이름:시작점:개수}              : 시작점부터 '개수'개만큼 가져옴

${변수이름:시작점:-(개수)}          : 시작점부터 + '개수'개 만큼뒤에서 가져옴

${변수이름:${#변수이름}-3:${#변수이름}}  : 맨뒤에서 -3 만큼 가져옴

${변수이름:(-3)}                            : 맨뒤에서 -3 만큼 가져옴

${#타겟변수}                                : 변수의 총 index 값을 구함

 

------

${타겟변수#*특정단어}

- 앞에서 찾고 / 앞에서(왼쪽)부터 [특정단어] 까지 자름

 

${타겟변수##*특정단어}

- 뒤에서 찾고 / 앞에서(왼쪽)부터 [특정단어] 까지 자름

 

${타겟변수%특정단어*}

- 뒤에서 찾고 / 뒤에서(오른쪽)부터 [특정단어] 까지 자름

 

${타겟변수%%특정단어*}

- 앞에서 찾고 / 뒤에서(오른쪽)부터 [특정단어] 까지 자름

 

문자열 삭제 ( 자주 씀 )

~$ echo ${PWD##*/}

-현재 최상위 디렉토리 네임

 

~$ echo ${PWD#*$HOME}

- 현재 위치에서 HOME위치를 제외한 경로

 

~$ file_path=$(find $HOME -name 'main_python_file.py')

~$ echo ${file_path%%main_python_file.py*}

- "main_python_file.py"라는 파일을 찾고 해당 파일이 있는 디렉토리 경로

 

 

문자열 치환 ( 자주 쓰는 방법 ) 

물론 위의 방법을 쓸 수 있지만, 사실 pop 기능 같은경우는 '' 빈스트링으로 치환하면 같은 결과가 나온다.

따라서 치환으로만 쓴다면 주로 3가지를 많이씀

 

${변수명/타겟/변환문자}      : 타겟을 변환문자로 앞에서부터 찾아 변환

 

 2069  tmp=${path%b*}

 2070  index=${#tmp}
 2071  cutted_str=${path:$index:${#path}}
 2072  attach_str=${cutted_str/b/a}
 2073  echo ${path%b*}$attach_str

: 뒤에서 b까지의 자른 위치의 인덱스를 가지고, 잘린부분을 가져와서 b->a 로 치환 후, 붙임.

결론 : 타겟을 변환문자 뒤에서부터 찾아 변환

 

${변수명//타겟/변환문자}     : 타겟을 변환문자로   

 

 

TIP> 

/ <- 이런 문자열 치환시 앞에  '\' <-원화표시를 붙여준다

 


exit 0        : return 0

eval          : python eval와 같다고 생각하면 된다.

read          : input 함수 ex) "read username"    입력시 $username 에 값 삽입. 

 

eval 예시 :

 

 

 

 

 


$ 관련 정리

예제 :

사진

코드 :

#!/bin/bash
set -e  # 코드중 return 값 실패 시(0이외의 값) 바로 프로세스 종료

set -x  # 배시 명령어 실행전에 무슨명령어가 실행 될지 미리 출력해줌

set +e , set +x 하면 반대로 동작함

 

 

$@
if [ $? == 0 ]  # '-eq' == '==' , '-ne' == '!='
then
        echo "[ $@ ] command returned [ $? ] success"
else
        echo "[ $@ ] command returned [ $? ] failed"
        echo "so try again"
        for((i=0;i<3;i++))
        do
                sleep 1
                echo "tryed num : [ $i ]"
                $@
        done
fi

echo ' '
$CMD mkdir cmd_test

 

 

출력값 : 2개 // 유효한 명령어 vs 유효하지않은 명령어

유효한 명령어를 썼을떄 :

 

유효하지 않은 명령어를 썻을때 :

 

 


if 문 :

eval $@
if [ $? -eq 0 ];
then
        echo 'executed successfully'
        $CMD mkdir test_dir
else
        echo "terminated unsuccessfully"
fi
# 실행 : source test.sh 'ls'
# 출력 : executed successfully

a=0
if [ $a -eq 0 ];
then
        echo 'a == 0 True'
else
        echo 'false'
fi
# 출력 : a == 0 True

 

만약 if 문에 조건을 2개 이상 쓴다면 [ ~~ ] -> [ [ (~~ && ~~) ] ]  이런식으로 [] 를 두번 써줘야한다.

ex ) if [[ ( $n -eq 15 || $n  -eq 45 ) ]]

이렇게 아니면

if [ $a == 1 ] || [ $a == 3 ]

이런식으로 or 나 and 문을 풀어 나가줘야한다.

 

if 문 하나더  ( if 문법이 2개다. ; 를 쓰는 문법이 있는데 그거랑 null 타입 체크 용 예제 )

a=$(find ~ -name 'NULLRETRUN')  # a에는 '' 값이 들어가 있음
if [ -z $a ]; then
        echo 'a is null'
else
        echo 'a is not null'
fi;
# 출력 : a is null

 

if 문 하나더  ( /bin/bash -c ' ~~~ ' 로 실행 하는 경우 )

이거는 그냥 콘솔창에 실행해도 되고

~~.sh 로 저장해서 source 로 실행해도 된다.

이게 source 실행 이고

 

이렇게 콘솔창에서 실행도 가능함.

 

if 문 하나더더  ( 정수 비교 )

도  os_version 은 '16' 이라는 string 값이다.

따라서 $((os_version)) 으로 int 값으로 변경해주고

[ ] <- 대신에 ( ) 를 사용하여 비교해 동작한다.

if (( $((os_version)) < '20' )); then
  echo "20 이하";
else
  echo "20 이상";
fi

for 문 :

무한루프

for (( ; ; ))
do
    echo "Doing something"
    sleep 1
done

#---------------------------------------------------------------------------------------------------------

for (( ; ; ))
do

    echo "Doing something"
    sleep 1
done

# ---------------------------------------------------------

+ break 문

# for (( ; ; ))
for (( i=0; i<=10; i++ ))
do
    if [ $i -eq 5 ]
    then
        continue
    fi

    if [ $i -eq 8 ]
    then
        break
    fi

    echo $i

done

 

배열 :

키워드 : arr=($(명령어))  //  ${변수[인덱스]}  //  ${#arr[@]} 

띄어쓰기로 받아지는 명령어의 경우 배열로 받을 수 있다.

ex ) ls , find명령어 등등등등

이런식으로 폴더구성이 되어있다 치고

ls로 간단 예제 :

하단에 보면 ( $ ( ls ) )   이런식으로 괄호를 두번쳐서 넘긴다. 그러면 배열로 가져간다.

 

find명령어로 for문이랑 결합한 예제

타겟 디렉터리에 다이나믹하게 들어오는 경우 

setup_bash_path=($(find . -name 'install'))
for((i=0;i<${#setup_bash_path[@]};i++)); do
        #echo "source ${PWD}/${setup_bash_path[i]}/setup.bash --extend" >> ~/.bashrc
        echo "${setup_bash_path[i]}"
        source ./${setup_bash_path[i]}/setup.bash --extend
done

 

날짜 나타내기

 

echo $(date "+%y%m%d_%H%M")

230803_1544 <- 이렇게 나옴

Y 면 2023 y 면 23

 

 

 

 

'리눅스 관련 > shell scrtipt 쉘' 카테고리의 다른 글

정규표현식  (0) 2023.02.09
expect -> interactive 자동화  (0) 2022.12.20

댓글