문자

문자열 에서 jq

6개의 연습 문제

문자열 소개

jq는 JSON과 같은 데이터 타입을 지원한다는 점을 기억해 두어요. JSON은 문자열을 이렇게 설명해요:

문자열은 0개 이상의 유니코드 문자 시퀀스이며, 큰따옴표로 감싸고 백슬래시 이스케이프를 사용해 표현해요.

이스케이프 시퀀스

문자열 안에서는 백슬래시 문자를 사용해 "특수한" 문자를 넣어요:

  • \": 문자 그대로의 큰따옴표
  • \\: 문자 그대로의 백슬래시
  • 공백 문자: \n, \t, \r, \f, \b
  • 유니코드 문자: \uAAAA (A는 16진수 숫자)

문자열 길이

문자의 개수를 구하려면 length 함수를 사용해요.

$ jq -cn --args  '$ARGS.positional[] | length' "Hello world!" "❄🌡🤧🤒🏥🕰😀"
12
7

실제 바이트 수를 구하려면 utf8bytelength 함수를 사용해요.

$ jq -cn --args  '$ARGS.positional[] | utf8bytelength' "Hello world!" "❄🌡🤧🤒🏥🕰😀"
12
27

부분 문자열

슬라이스 표기법을 사용하면 부분 문자열을 추출할 수 있어요. 문법은 .[i:j]예요. 반환되는 부분 문자열의 길이는 j - i이고, 인덱스 i(포함)부터 인덱스 j(미포함)까지의 문자를 반환해요. 각 인덱스는 음수가 될 수 있는데, 그러면 문자열의 끝에서부터 거꾸로 세요. 각 인덱스는 생략할 수도 있고, 그러면 문자열의 시작이나 끝을 가리켜요. 인덱스는 0부터 시작해요.

"abcdefghij"[3:6]   # => "def"
"abcdefghij"[3:]    # => "defghij"
"abcdefghij"[:-2]   # => "abcdefgh"

연결

문자열을 이어 붙이려면 +를 사용해요:

"Hello" + " " + "world!"
# => "Hello world!"

문자열 배열이 주어졌을 때는 add를 사용해요:

["Hello", " ", "world!"] | add
# => "Hello world!"

분할과 결합

문자열을 나눌 때는 split/1 함수나 / 연산자를 사용해요:

"Hello beautiful world!" | split(" ")   # => ["Hello", "beautiful", "world!"]
"Hello beautiful world!" / " "          # => ["Hello", "beautiful", "world!"]

split/1의 반대는 join/1이에요.

문자열을 문자 배열로 바꾸는 일은 자주 필요해요. 이를 위한 방법이 두 가지 있어요:

  1. 빈 문자열을 기준으로 나누기

    "Hi friend 😀" / ""   # => ["H","i"," ","f","r","i","e","n","d"," ","😀"]
    
  2. explode로 코드포인트 배열 만들기

    "Hi friend 😀" | explode   # => [72,105,32,102,114,105,101,110,100,32,128512]
    

    implode는 explode의 반대예요.

부분 문자열의 인덱스 찾기

index/1 함수를 사용해요. 인덱스는 0부터 시작해요.

"hello" | index("el")'   # => 1

문자열에 부분 문자열이 없으면 결과는 null이에요.

"hello" | index("elk")   # => null

그 밖에 유용한 함수로는 rindex/1과 indices가 있어요.

문자열 보간

문자열 안에서 \(expression) 시퀀스는 그 표현식의 _결과_를 문자열에 넣어요:

"The current datetime is \(now | strflocaltime("%c"))"   # => "The current datetime is Wed Nov 16 17:06:33 2022"

대소문자 변환

ascii_downcase와 ascii_upcase 함수를 사용해 문자열의 대소문자를 바꿔요.

문자열을 숫자로 변환하기

tonumber 함수를 사용해 문자열에서 숫자를 만들어요.

문자열을 숫자로 변환할 수 없으면 오류가 발생하므로 try-catch가 필요할 수 있어요.

$ jq -cn --args '$ARGS.positional[] | [., tonumber]' 42 3.14 oops 1e6 0xbeef
["42",42]
["3.14",3.14]
jq: error (at <unknown>): Invalid numeric literal at EOF at line 1, column 4 (while parsing 'oops')

$ echo $?
5

$ jq -cn --args '$ARGS.positional[] | try [., tonumber] catch "not a number"' 42 3.14 oops 1e6 0xbeef
["42",42]
["3.14",3.14]
"not a number"
["1e6",1000000]
"not a number"

JSON 숫자에는 일부 언어가 지원하는 16진수나 8진수 형태가 없다는 점에 주의해요.

그 밖의 함수

이 함수들에 대한 자세한 내용은 매뉴얼을 확인해요:

  • 문자열 반복: *
  • 포함 여부 검사: contains/1, inside/1, indices/1, index/1, rindex/1, startswith/1, endswith/1
  • 공백 제거: lsrimstr/1, rtrimstr/1
  • 포맷 함수: @text, @json, @html, @uri, @csv, @tsv, @sh, @base64, @base64d

정규 표현식

jq는 정규 표현식을 풍부하게 지원해요. 이 주제는 나중 강의에서 다뤄요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요

문자열 배우기

연습이 잠겨 있어요

문자열 개념을 연습하려면 연습 문제 8개를 더 잠금 해제해요