본문 바로가기
IT일반/Linux

Command Line - 문자열과 수

by 버섯도리 2022. 6. 17.
[cmd_test@btjeon-naver ~]$ a="foo"
[cmd_test@btjeon-naver ~]$ echo "$a_file"

[cmd_test@btjeon-naver ~]$ echo "${a}_file"
foo_file

변수의 내용에 문자열 추가하려 할 때, 중괄호({}) 사용

 

[cmd_test@btjeon-naver ~]$ foo=
[cmd_test@btjeon-naver ~]$ 
[cmd_test@btjeon-naver ~]$ echo ${foo:-"substitute value if unset"}
substitute value if unset
[cmd_test@btjeon-naver ~]$ echo $foo

[cmd_test@btjeon-naver ~]$ foo=bar
[cmd_test@btjeon-naver ~]$ echo ${foo:-"substitute value if unset"}
bar
[cmd_test@btjeon-naver ~]$ echo $foo
bar

${parameter:-word} : parameter가 설정되어 있지 않거나(즉, 존재하지 않으면) 비어있다면, 이 확장 결과는 word의 값이 된다.

 

[cmd_test@btjeon-naver ~]$ foo=
[cmd_test@btjeon-naver ~]$ echo ${foo:="default value if unset"}
default value if unset
[cmd_test@btjeon-naver ~]$ echo $foo
default value if unset
[cmd_test@btjeon-naver ~]$ foo=bar
[cmd_test@btjeon-naver ~]$ echo ${foo:="default value if unset"}
bar
[cmd_test@btjeon-naver ~]$ echo $foo
bar

${parameter:=word} : 등호를 사용하면 word의 값이 parameter에 할당된다.

 

[cmd_test@btjeon-naver ~]$ foo=
[cmd_test@btjeon-naver ~]$ echo ${foo:?"parameter is empty"}
-bash: foo: parameter is empty
[cmd_test@btjeon-naver ~]$ echo $?
1
[cmd_test@btjeon-naver ~]$ foo=bar
[cmd_test@btjeon-naver ~]$ echo ${foo:?"parameter is empty"}
bar
[cmd_test@btjeon-naver ~]$ echo $?
0

${parameter:?word} : 물음표를 사용할 때 parameter가 설정되지 않거나 비어있다면 이 확장으로 오류가 발생하며 스크립트는 종료된다. 그리고 word의 값은 표준 출력으로 보내진다.

 

[cmd_test@btjeon-naver ~]$ foo=
[cmd_test@btjeon-naver ~]$ echo ${foo:+"substitute value if set"}

[cmd_test@btjeon-naver ~]$ foo=bar
[cmd_test@btjeon-naver ~]$ echo ${foo:+"substitute value if set"}
substitute value if set
[cmd_test@btjeon-naver ~]$ echo $foo
bar

${parameter:+word} : 더하기를 사용할 때 parameter가 설정되지 않거나 비어있다면 이 확장은 아무런 결과를 표시하지 않는다. 만약 parameter가 비어있지 않다면 parameter word의 값으로 대체된다. 하지만 parameter의 값은 변하지 않는다.

 

[cmd_test@btjeon-naver ~]$ echo ${!BASH*}
BASH BASHOPTS BASHPID BASH_ALIASES BASH_ARGC BASH_ARGV BASH_CMDS BASH_COMMAND BASH_COMPLETION_COMPAT_DIR BASH_LINENO BASH_REMATCH BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
[cmd_test@btjeon-naver ~]$ echo ${!BASH@}
BASH BASHOPTS BASHPID BASH_ALIASES BASH_ARGC BASH_ARGV BASH_CMDS BASH_COMMAND BASH_COMPLETION_COMPAT_DIR BASH_LINENO BASH_REMATCH BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION

${!prefix*}, ${!prefix@} : 이 확장은 prefix로 시작되는 이미 존재하는 변수의 이름을 반환한다. (두 형식이 동일하게 동작한다.)

 

[cmd_test@btjeon-naver ~]$ foo="This string is long."
[cmd_test@btjeon-naver ~]$ echo "'$foo' is ${#foo} characters long."
'This string is long.' is 20 characters long.

${#parameter} : 이 확장은 parameter가 포함된 문자열의 길이로 확장된다.

 

[cmd_test@btjeon-naver ~]$ foo="This string is long."
[cmd_test@btjeon-naver ~]$ echo ${foo:5}
string is long.
[cmd_test@btjeon-naver ~]$ echo ${foo:5:6}
string
[cmd_test@btjeon-naver ~]$ echo ${foo: -5}
long.
[cmd_test@btjeon-naver ~]$ echo ${foo: -5:2}
lo

${parameter:offset}, ${parameter:offset:length} : 이 확장은 parameter에 포함된 문자열의 일부를 추출하기 위해 사용된다. offset에 위치한 문자부터 시작해서 length를 명시하지 않으면 문자열 끝까지 추출한다.

 만약 offset 값이 음수이면 문자열의 일부분이 아닌 끝부분부터 시작하라는 것을 의미한다.${parameter:-word} 확장과 혼동을 막기 위해 음수 값은 반드시 앞에 공백을 두어야 한다.

 

[cmd_test@btjeon-naver ~]$ foo=file.txt.zip
[cmd_test@btjeon-naver ~]$ echo ${foo#*.}
txt.zip
[cmd_test@btjeon-naver ~]$ echo ${foo##*.}
zip
[cmd_test@btjeon-naver ~]$ echo ${foo%.*}
file.txt
[cmd_test@btjeon-naver ~]$ echo ${foo%%.*}
file

${parameter:#pattern}, ${parameter:##pattern} : 이 확장은 매개변수가 가진 문자열에서 pattern(와일드카드 패턴)에 정의된 내용으로 시작하는 부분을 제거한다. # 형식은 최단 길이로 일치하는 것을 제거하고 ## 형식은 최장 길이로 일치하는 것을 제거한다.

${parameter:%pattern}, ${parameter:%%pattern} : #, ##와 동일하지만 문자열의 시작이 아닌 끝에서부터 제거한다.

 

[cmd_test@btjeon-naver ~]$ foo=JPG.JPG
[cmd_test@btjeon-naver ~]$ echo ${foo/JPG/jpg}
jpg.JPG
[cmd_test@btjeon-naver ~]$ echo ${foo//JPG/jpg}
jpg.jpg
[cmd_test@btjeon-naver ~]$ echo ${foo/#JPG/jpg}
jpg.JPG
[cmd_test@btjeon-naver ~]$ echo ${foo/%JPG/jpg}
JPG.jpg

${parameter/pattern/string}, ${parameter//pattern/string}, ${parameter/#pattern/string}, ${parameter/%pattern/string} :

 이 확장은 parameter의 내용을 치환한다. 와일드 카드 pattern과 일치하는 텍스트를 발견하면 string의 내용으로 대치된다.

 - / 형식은 일치하는 첫 부분만 대체한다.

 - // 형식은 일치하는 모든 부분을 대체한다.

 - /# 형식은 문자열의 시작 부분에서 일치하는 첫 부분만 대체한다.

 - /% 형식은 문자열의 끝 부분에서 일치하는 첫 부분만 대체한다.

 

[cmd_test@btjeon-naver ~]$ vi longest_word3.sh
------------------------------------------------------------------------------------------
#!/bin/bash

# longest-word3 : find longest string in a file

for i; do
        if [[ -r $i ]]; then
                max_word=
                max_len=0
                for j in $(strings $i); do
                        len=${#j}
                        if (( len > max_len )); then
                                max_len=$len
                                max_word=$j
                        fi
                done
                echo "$i: '$max_word' ($max_len characters)"
        fi
done
------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ time ./longest_word2.sh dirlist-usr-bin.txt 
dirlist-usr-bin.txt: 'abrt-action-check-oops-for-hw-error' (36 characters)

real	0m1.405s
user	0m0.920s
sys	0m0.481s
[cmd_test@btjeon-naver ~]$ time ./longest_word3.sh dirlist-usr-bin.txt 
dirlist-usr-bin.txt: 'abrt-action-check-oops-for-hw-error' (35 characters)

real	0m0.011s
user	0m0.008s
sys	0m0.003s

$(echo $j | wc -c) 명령을 ${#j} 매개변수 확장으로 바꾼 후 time 명령어를 사용하여 두 버전의 효율성을 비교하였다. 이전 스크립트는 1.405초, 바꾼 스크립트는 0.011초 걸렸다.

 

[cmd_test@btjeon-naver ~]$ echo $(( 5 / 2 ))
2
[cmd_test@btjeon-naver ~]$ echo $(( 5 % 2 ))
1
[cmd_test@btjeon-naver ~]$ vi modulo.sh
------------------------------------------------------------------------------------------
#!/bin/bash

# modulo : demonstrate the modulo operator

for ((i - 0; i <= 20; i = i + 1)); do
        remainder=$((i % 5))
        if (( remainder == 0 )); then
                printf "<%d> " $i
        else
                printf "%d " $i
        fi
done
------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./modulo.sh 
<0> 1 2 3 4 <5> 6 7 8 9 <10> 11 12 13 14 <15> 16 17 18 19 <20>

기본 연산자 사용 예제

 

[cmd_test@btjeon-naver ~]$ foo=1
[cmd_test@btjeon-naver ~]$ echo $((foo++))
1
[cmd_test@btjeon-naver ~]$ echo $foo
2
[cmd_test@btjeon-naver ~]$ foo=1
[cmd_test@btjeon-naver ~]$ echo $((++foo))
2
[cmd_test@btjeon-naver ~]$ echo $foo
2
[cmd_test@btjeon-naver ~]$ vi modulo2.sh
--------------------------------------------------------------------------------------
#!/bin/bash

# modulo2 : demonstrate the modulo operator

for ((i - 0; i <= 20; ++i)); do
        if (( (i % 5) == 0 )); then
                printf "<%d> " $i
        else
                printf "%d " $i
        fi
done
printf "\n"
--------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./modulo2.sh 
<0> 1 2 3 4 <5> 6 7 8 9 <10> 11 12 13 14 <15> 16 17 18 19 <20>

대입 연산자 사용 예제

 

[cmd_test@btjeon-naver ~]$ for ((i=0;i<8;++i)); do echo $((1<<i)); done
1
2
4
8
16
32
64
128

왼쪽 비트 연산자를 사용하여 2의 배수를 생성하는 예제

 

[cmd_test@btjeon-naver ~]$ if ((1)); then echo "true"; else echo "false"; fi
true
[cmd_test@btjeon-naver ~]$ if ((0)); then echo "true"; else echo "false"; fi
false
[cmd_test@btjeon-naver ~]$ a=0
[cmd_test@btjeon-naver ~]$ ((a<1?++a:--a))
[cmd_test@btjeon-naver ~]$ echo $a
1
[cmd_test@btjeon-naver ~]$ ((a<1?++a:--a))
[cmd_test@btjeon-naver ~]$ echo $a
0
[cmd_test@btjeon-naver ~]$ ((a<1?(a+=2):(a-=2)))
[cmd_test@btjeon-naver ~]$ echo $a
2
[cmd_test@btjeon-naver ~]$ ((a<1?(a+=2):(a-=2)))
[cmd_test@btjeon-naver ~]$ echo $a
0

논리 연산자 사용 예제

 

[cmd_test@btjeon-naver ~]$ vi arith-loop.sh
---------------------------------------------------------------------------------------------
#!/bin/bash

# arith-loop : script to demonstrate arithmetic operators

finished=0
a=0
printf "a\ta**2\ta**3\n"
printf "=\t====\t====\n"

until ((finished)); do
        b=$((a**2))
        c=$((a**3))
        printf "%d\t%d\t%d\n" $a $b $c
        ((a<10?++a:(finished=1)))
done
---------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./arith-loop.sh 
a	a**2	a**3
=	====	====
0	0	0
1	1	1
2	4	8
3	9	27
4	16	64
5	25	125
6	36	216
7	49	343
8	64	512
9	81	729
10	100	1000

산술 연산자를 이용해 간단한 계산 표를 생성하는 스크립트

 

[cmd_test@btjeon-naver ~]$ vi foo.bc
------------------------------------------------------------------------------------------
/* A very simple bc script */

2 + 2
------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ bc foo.bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
4
quit

bc 프로그램 사용 예제

 

[cmd_test@btjeon-naver ~]$ bc -q
2 + 2
4
quit

bc 프로그램 대화식 사용 예제

 

[cmd_test@btjeon-naver ~]$ bc < foo.bc
4
[cmd_test@btjeon-naver ~]$ bc <<< "2+2"
4

표준 입력을 통해 bc 스크립트를 전달하는 것도 가능하다.

 

[cmd_test@btjeon-naver ~]$ vi loan-calc.sh
---------------------------------------------------------------------------------------------
#!/bin/bash

# loal-calc : script to calculate monthly loan payments

PROGNAME=$(basename $0)

usage () {
        cat <<- EOF
        Usage: $PROGNAME PRINCIPAL INTEREST MONTHS

        Where:

        PRINCIPAL is the amount of the loan.
        INTEREST is the APR as a number (7% = 0.07).
        MONTHS is the length of the loan's term.

        EOF
}

if (($# != 3)); then
        usage
        exit 1
fi

principal=$1
interest=$2
months=$3

bc <<- EOF
        scale = 10
        i = $interest / 12
        p = $principal
        n = $months
        a = p * ((i * ((1 + i) ^ n)) / (((1 + i) ^ n) - 1))
        print a, "\n"
EOF
---------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./loan-calc.sh 135000 0.0775 180
1270.7222490000

bc 명령어를 사용하여 월별 상환금을 계산하는 예제이다. 결과에 대한 소수점 정밀도를 bc 스크립트의 특별한 scale 변수로 설정하였다.

 

 

 

 

 

 

출처 : 리눅스 커맨드라인 완벽 입문서

 

'IT일반 > Linux' 카테고리의 다른 글

VI editor reference  (0) 2022.06.21
Command Line - 배열  (0) 2022.06.18
Command Line - 흐름 제어 : for 루프  (0) 2022.06.13
Command Line - 위치 매개변수  (0) 2022.06.08
Command Line - 흐름 제어 : Case 분기  (0) 2022.06.07