Linux/Bash shell

[Linux-vim] vim에디터 사용하기 5 - function (함수), jq(JSON 파싱), 다른 언어 활용

걍작 2022. 3. 15. 02:16

# 정리

** python3 : 사용자친화적인 언어지만 초기엔 불편한 부분들이 있어 개선되는 중이며, 현재 3버젼이 많이 쓰이고 있다.
** 함수를 만들어서 사용하는 이유 : 재사용성을 용이하게 하기 위해
(같은 기능을 여러번 사용할 때 편하라고 = 코딩을 덜하기 위해서(유지보수 포함) = 개발 시간을 줄이기 위해서 )

# otherlanguage - 다른 언어 가져오기
//($언어명 -c "명령문") 형태로 다른 언어를 가져와 사용할 수 있다.
 - $python -c "print(3*5)" 
//다른 언어의 명령문의 결과 값도 $( )안에 담아 변수에 넣을 수 있다.
<사실 효율적인 방법은 아니지만, 할 수 있다는 것을 아는게 중요!>
 - $()를 이용해서 result 에 다른 언어의 결과를 넣은 것을 볼 수 있다. 
 - $($python -c "print(3*5)" ) - 파이썬 언어의 명령구문의 결과(15)를 값으로 가진다.


# function  함수
( 1. Basic )
//함수를 만들 때 염두해야 할 4가지 ( 인풋 있고 없고 / 리턴 있고 없고 )
 - 쉘스크립트는 리턴 값이 텍스트 반환밖에 없다는 특징이 있다.
//쉘에는 함수만 블록{}이 있다. 
//쉘스크립트함수는 타입이 없이 함수명이 바로온다.
//함수 콜 할때 ()를 붙이지 않는다. (ex. testFn() - X / testFn - O)
 - 함수이름을 바로 변수에 할당하면 텍스트로 인식되며, 함수의 결과를 불러오려면 $( )안에 넣어야한다.
//return을 적지 않아도, 기본적으로 return이 들어있다.
 - 쉘에서는 return 뒤에 내용이 리턴되는 것이 아니라, 함수 내의 출력문 전체의 결과 값이 리턴되는 것에 주의할 것

( 2. 변수 활용 )
//함수 안에서 외부 변수를 받아오거나 내부 변수를 활용할 수 있다.
//자바, 자바스크립트와 달리 함수 내부 (블록내부) 에 있는 변수를 밖에서도 사용할 수 있다.
 - $local - 밖에서는 못쓰게 만드는 방법 >> 지역변수로 변경

( 3. 행렬 활용 ) 
//함수의 결과 값은 행렬로 들어오는 것이 아니라 텍스트로 들어온다.
 - 함수 결과 값을 행렬로 하고 싶으면 밖에 ( )로 감싸줘야한다.
 - 텍스트의 나열은 for in으로 출력해야하지만, 행렬로 만들면 전통적인 for문으로도 출력할 수 있다.

( 4. 위치 매개변수($1,$2..) 활용 )
//$( )로 감싸면 한 줄의 텍스트값으로 결과값이 모여서 나옴


#jq - json 파싱
//jq패키지를 추가로 설치해야 사용 가능하다.
 - $sudo apt install -y jq
//JSON 형식으로 쓰여진 텍스트를 파싱할 때 사용한다.
 -  [] - 배열 (인덱스-값) , {} - 객체 (키-값)
 - 나중에 레스트 컨트롤러에서 읽어온 값이 제이슨일 때 활용할 수 있다.
 - Java의 Jackson 형식, JS의 object 형식과 같음
//Jq를 사용하는 2 가지 방법
  ** 웹페이지를 cat으로 읽어오게되고, cat외에도 head /tail등 다양한 변화가 가능해서 1번이 더 자주 사용됨. 
 - cat으로 읽어들인 텍스트를 jq로 처리하는 방법(뒷 내용 참조) : cat sh17temp2.json |jq '.[0].id'
 - jq 단독으로 읽어오는 방법 : jq ".vo.id" sh17temp.json
//넘어온 데이터를 읽어내는 역할로 $cat 외에 $head / $tail 도 함께 활용할 수 있다. 
 - head 앞줄 읽기 / tail 뒷줄 읽기 (-숫자 : 읽는 줄 수 지정 옵션)
 - 넘어온 데이터에 특정 위치의 줄이 제이슨일 때 같이 활용한다.
// . 은 ~안에 라는 뜻임을 기억하자.
//데이터 안의 특정 인덱스나 키 값을 활용하여 특정 값만 읽어올 수 있다.
 - jq "." 파일명 : 파일 안 모든 값을 불러와줘 
 - jq ".vo" 파일명 :  "vo"에 있는 내용을 불러와줘
 - jq ".vo.id" 파일명 : "vo"가 가진 값 중 "id"값을 불러와줘 
 - jq ".arr" 파일명 : "arr"에 있는 내용을 불러와줘 
 - jq ".arr[1]" 파일명 : "arr" 배열 값 안에 1번 인덱스 값을 불러와줘
//curl과 jq를 혼합하여 웹상의 데이터를 읽어올 수 있다.
- $curl (-s옵션) 데이터 읽어올 때 통신 정보는 출력 안함
- $jq (-r옵션) 최종 값에 " "표시를 없애줘 (ex. "admin" >> admin) 
 * -r은 배열 데이터의 최종 키값으로 대응되는 최하위단의 데이터를 단독 출력할 때만 적용됨.

 

 

 

** python3 : 사용자친화적인 언어지만 초기엔 불편한 부분들이 있어 개선되는 중이며, 현재 3버젼이 많이 쓰이고 있다.

 

# otherlanguage - 다른 언어 가져오기

//($언어명 -c "명령문") 형태로 다른 언어를 가져와 사용할 수 있다.

 - $python3 - 파이썬(3) 부르기 ; 파이썬(3) 언어 안으로 들어가겠다. ( >>>exit() 종료 함수 /  >>>print() 출력 함수 )

 - $python -c "print(3*5)" 

 

 

//다른 언어의 명령문의 결과 값도 $( )안에 담아 변수에 넣을 수 있다.

<사실 효율적인 방법은 아니지만, 할 수 있다는 것을 아는게 중요!>

 - $()를 이용해서 result 에 다른 언어의 결과를 넣은 것을 볼 수 있다. 

 - $($python -c "print(3*5)" ) - 파이썬 언어의 명령구문의 결과(15)를 값으로 가진다.

#!/bin/bash
clear 
pwd
echo $0

echo "----------------------------"
x=3
y=5
echo $((x*y))

echo $(python -c "print($x*$y)")

result=$(python -c "print($x*$y)")
echo $result


exit 0

 


** 함수를 만들어서 사용하는 이유 : 재사용성을 용이하게 하기 위해

(같은 기능을 여러번 사용할 때 편하라고 = 코딩을 덜하기 위해서(유지보수 포함) = 개발 시간을 줄이기 위해서 )

 

# function  함수 - 1. Basic 

//함수를 만들 때 염두해야 할 4가지 ( 인풋 있고 없고 / 리턴 있고 없고 )

 - 쉘스크립트는 리턴 값이 텍스트 반환밖에 없다는 특징이 있다.

//쉘에는 함수만 블록{}이 있다. 

//쉘스크립트함수는 타입이 없이 함수명이 바로온다.

//함수 콜 할때 ()를 붙이지 않는다. (ex. testFn() - X / testFn - O)

 - 함수이름을 바로 변수에 할당하면 텍스트로 인식되며, 함수의 결과를 불러오려면 $( )안에 넣어야한다.

//return을 적지 않아도, 기본적으로 return이 들어있다.

 - 쉘에서는 return 뒤에 내용이 리턴되는 것이 아니라, 함수 내의 출력문 전체의 결과 값이 리턴되는 것에 주의할 것

#!/bin/bash
clear 
pwd
echo $0

echo "----------------------------"

testFn(){
echo "testFn()...a"
echo "testFn()...b"

#return exists evenif return wasn't written

}

#function call (testFn() >> X)
testFn

result=testFn
echo "return:"$result

result=$(testFn)
echo "return:"$result


exit 0

 

 

-------------------------------------------

# function  함수 - 2. 변수 활용 

//함수 안에서 외부 변수를 받아오거나 내부 변수를 활용할 수 있다.

//자바, 자바스크립트와 달리 함수 내부 (블록내부) 에 있는 변수를 밖에서도 사용할 수 있다.

 - $local - 밖에서는 못쓰게 만드는 방법 >> (아래 예문 참조) eng는 값이 안나오고 있다.

#!/bin/bash
clear 
pwd
echo $0

echo "----------------------------"

name_product="NoteBook"
readonly NAME="kim"


testFn(){
	echo "testFn()...a" $name_product
	echo "testFn()...b" $NAME

	kor=100
	echo "testFn...c" $kor

	local eng=99
	echo "testFn()...d" $eng
	
	#return

}

#function call
testFn

echo "----------------------------"
echo "name_product:"$name_product
echo "NAME"$NAME
echo "kor"$kor
echo "eng"$eng

#function call
result=$(testFn)
echo "return:"$result



exit 0

 

 

-------------------------------------------

# function  함수 - 3. 행렬 활용 

//함수의 결과 값은 행렬로 들어오는 것이 아니라 텍스트로 들어온다.

 - 함수 결과 값을 행렬로 하고 싶으면 밖에 ( )로 감싸줘야한다.

 - 텍스트의 나열은 for in으로 출력해야하지만, 행렬로 만들면 전통적인 for문으로도 출력할 수 있다.

#!/bin/bash
clear 
pwd
echo $0

echo "----------------------------"

score(){
echo 99 88 77
}

echo $(score)
str=$(score)
echo "str.length:"${#str}

for item in $(score)
do
echo $item
done

echo "----------------------------"
arr=($(score))
echo ${arr[@]}
echo "arr.length:"${#arr[@]}
echo ${arr[0]}
echo ${arr[1]}
echo ${arr[2]}


exit 0

 

 

-------------------------------------------

# function  함수 - 4. 위치 매개변수($1,$2..) 활용 

//$( )로 감싸면 한 줄의 텍스트값으로 결과값이 모여서 나옴

//토탈 합산을 밖에서 하면 실행명령이 없어서 $1,$2,$3에 값이 없음

//seq 명령으로 함수 3번 연속 콜함

#!/bin/bash
clear 
pwd
echo $0

echo "----------------------------"
testFn(){
	echo "testFn()..."
	echo $1 $2 $3
	echo $(($1+$2+$3))
	echo total=$(($1+$2+$3))
}

testFn 11 22 33

echo $(testFn 11 22 33)

#not defined position parameter($1, $2, $3)
#total=$$(($1+$2+$3))

echo "----------------------------"

sum(){
	
	fsum=0
	for item in $@
	do
		fsum=$((fsum+item))
	done
	echo sum=$fsum

}
sum 1 2 3 4 5 6 7 8 
echo $(sum 1 2 3 4 5 6 7 8)

for i in $(seq 3)
do
	sum 11 22 33
done


exit 0

 

 

-------------------------------------------

** 개발할 땐, 더미값으로 먼저 오류를 확인하고, read 같은 인풋 명령은 항상 마지막에 넣는다.

 

mission 1 : 성적처리 함수를 콜하면  3명의 성적을 받아서 출력하도록 만들어라.

(단, 함수 안에는 총점 평균 등급만 처리하고, 따로 루프를 돌려서 점수 받는 것과 함수 콜만 실행할 것)

<순서> //for가 3번 돌아가는지 확인 >> 더미값으로 넣고 $1,2,3,4로 실행 >> read문 추가

#!/bin/bash
clear
pwd
echo $0

echo "----------------------"

#name kor eng math total avg grade

score(){
   #echo "score()..."
   #echo $1 $2 $3 $4

   total=$(($2+$3+$4))
   avg=$((total/3))
   grade="A"

   if ((avg>=90));then
      grade="A"
   elif ((avg>=80));then
      grade="B"

   elif ((avg>=70));then
      grade="C"

   elif ((avg>=60));then
      grade="D"

   else
      grade="F"

   fi

   printf "name[%s]: kor[%d],eng[%d],math[%d],total[%d],avg[%.2f],grade[%s]\n" $1 $2 $3 $4 $total $avg $grade

}


for i in $(seq 3)
do
   read -p "input name:" name
   read -p "input kor:" kor
   read -p "input eng:" eng
   read -p "input math:" math
   echo $(score $name $kor $eng $math)
done


exit 0

 

 

 

mission 2 : 성적처리 함수를 콜하면  3명의 성적을 받아서 출력하도록 만들어라. (값을 배열로 받아볼 것)

// list 생성 - 시퀀스 0~2 - 리스트[인덱스] 값넣기 - 출력문 배열

// 값 넣는게 바로 이어지는 차이가 있다.

// printf로 리턴값을 만들 때는 장식적인 문자열이 들어가지 않도록 주의 필요

#!/bin/bash
clear 
pwd
echo $0

echo "----------------------------"

#name kor eng math total avg grade

score(){

	total=$(($2+$3+$4))
	avg=$((total/3))
	grade="A"


	if((avg>=90));then
		grade="A"

	elif((avg>=80));then
		grade="B"

	elif((avg>=70));then
		grade="c"

	elif((avg>=60));then
		grade="D"

	else
		grade="F"

	fi


	printf "%s %d %d %d %d %.2f %s" $1 $2 $3 $4 $total $avg $grade

}

list=()
for i in $(seq 0 2);
do
	read -p "input name:" name
	read -p "input kor:" kor
	read -p "input eng:" eng
	read -p "input math:" math

	#name="kim"
	#kor=11
	#eng=22
	#math=33

	list[i]=$(score $name $kor $eng $math)
done

echo ${list[@]}

echo "---------------------------------"

for item in "${list[@]}"
do
	echo $item
	
done


exit 0

 


 

 

#jq - json을 파싱하는 패키지(라이브러리) 

 

//jq패키지를 추가로 설치해야 사용가능하다.

 - $sudo apt install -y jq

//JSON 형식으로 쓰여진 텍스트를 파싱할 때 사용한다.

 -  [] - 배열 (인덱스-값) , {} - 객체 (키-값)

 - 나중에 레스트 컨트롤러에서 읽어온 값이 제이슨일 때 활용할 수 있다.

 - Java의 Jackson 형식, JS의 object 형식과 같

 

 

//Jq를 사용하는 2 가지 방법

  ** 웹페이지를 cat으로 읽어오게되고, cat외에도 head /tail등 다양한 변화가 가능해서 1번이 더 자주 사용됨. 

 - cat으로 읽어들인 텍스트를 jq로 처리하는 방법(뒷 내용 참조) : cat sh17temp2.json |jq '.[0].id'

 - jq 단독으로 읽어오는 방법 : jq ".vo.id" sh17temp.json

//넘어온 데이터를 읽어내는 역할로 $cat 외에 $head / $tail 도 함께 활용할 수 있다. 

 - head 앞줄 읽기 / tail 뒷줄 읽기 (-숫자 : 읽는 줄 수 지정 옵션)

 - 넘어온 데이터에 특정 위치의 줄이 제이슨일 때 같이 활용한다.

 

 

// . 은 ~안에 라는 뜻임을 기억하자.

//데이터 안의 특정 인덱스나 키 값을 활용하여 특정 값만 읽어올 수 있다.

 - jq "." 파일명 : 파일 안 모든 값을 불러와줘
 - jq ".vo" 파일명 :  "vo"에 있는 내용을 불러와줘

 - jq ".vo.id" 파일명 : "vo"가 가진 값 중 "id"값을 불러와줘
 - jq ".arr" 파일명 : "arr"에 있는 내용을 불러와줘
 - jq ".arr[1]" 파일명 : "arr" 배열 값 안에 1번 인덱스 값을 불러와줘

 

<jq 단독으로 읽어오는 방법>

#!/bin/bash
clear 
pwd
echo $0

echo "----------------------------"

cat > sh17temp.json << END
{
"name":"kim",
"vo":{"id":"admin"},
"arr":[11,22,33]
}
END

echo "----------------------------"
cat sh17temp.json

echo "----------------------------"
#sudo apt install -y jq

echo "----------------------------"
jq "." sh17temp.json

echo "----------------------------"
jq ".vo" sh17temp.json

echo "----------------------------"
jq ".arr" sh17temp.json

echo "----------------------------"
jq ".vo.id" sh17temp.json

echo "----------------------------"
jq ".arr[0]" sh17temp.json
jq ".arr[1]" sh17temp.json
jq ".arr[2]" sh17temp.json

exit 0

 

 

 

<cat으로 읽어들인 텍스트를 jq로 처리하는 방법>

echo "----------------------------"
cat > sh17temp2.json << END
[
{"id":"admin1","pw":"hi1234561"},
{"id":"admin2","pw":"hi1234562"},
{"id":"admin3","pw":"hi1234563"}
]
END

cat sh17temp2.json

echo "----------------------------"
cat sh17temp2.json |jq '.'
echo "----------------------------"
cat sh17temp2.json |jq '.[0]'
echo "----------------------------"
cat sh17temp2.json |jq '.[0].id'
cat sh17temp2.json |jq '.[0].pw'
echo "----------------------------"

 

//curl과 jq를 혼합하여 웹상의 데이터를 읽어올 수 있다.

- $curl (-s옵션) 데이터 읽어올 때 통신 정보는 출력 안함

- $jq (-r옵션) 최종 값에 " "표시를 없애줘 (ex. "admin" >> admin) 

 * -r은 배열 데이터의 최종 키값으로 대응되는 최하위단의 데이터를 단독 출력할 때만 적용됨.