Bash: 알파벳 문자가 처음 발생한 후 변수 분할

Bash: 알파벳 문자가 처음 발생한 후 변수 분할

crontab의 한 줄을 포함하는 변수가 있습니다

예를 들어:

0 22 * * 1-5 echo hello

2개의 변수로 나누고 싶은데, 하나의 변수는 작업 기간을 숫자나 별표로 나타내고, 다른 변수는 작업 실행 시 실행할 명령을 나타냅니다.

그래서 알파벳 문자가 처음 나타날 때 문자열을 분할하는 방법을 찾아야 하는데 어떻게 해야 할지 모르겠습니다.

답변1

이는 정확히 귀하가 찾고 있는 것이 아니지만 귀하의 사용 사례에 적합해야 합니다. 행을 변수에 정의된 대로 공백과 탭으로 구분된 6개의 변수로 읽습니다 IFS.

수정된 crontab 항목의 예:

$ line='0   22  * * 1-5 echo "foo  bar   baz"'
$ IFS=$'\t ' read -r a b c d e cmd <<<"$line"
$ echo "$a $b $c $d $e"
0 22 * * 1-5
$ echo "$cmd"
echo "foo  bar   baz"

처음 5개 필드의 여러 공백(또는 탭)은 단일 공백 ​​문자로 압축되지만 명령의 공백/탭은 변경되지 않습니다. "$a $b $c $d $e"필요한 경우 단일 변수에 할당할 수 있습니다.

답변2

이는 다음을 통해 수행할 수 있습니다.쉘 매개변수 확장그리고패턴 매칭

$ line='0 22 * * 1-5 echo hello'
$ prefix=${line%%[[:alpha:]]*}     #(a)
$ echo "$prefix"
0 22 * * 1-5 
$ suffix=${line#"$prefix"} .       #(b)
$ echo "$suffix"
echo hello

a: 끝부터 시작하여 알파와 일치하는 가장 긴 부분 문자열과 그 뒤에 임의의 문자를 찾아 $line에서 제거합니다.

b: 처음부터 시작하여 $line에서 접두사 test를 제거합니다.

답변3

내 생각에는 를 사용하여 이 작업을 수행할 수 있다고 생각합니다 awk. 특히 태그가 쉘 스크립트에서 사용하고 싶다는 것을 나타내기 때문입니다. 아래 코드 조각을 살펴보세요. 다른 응답자를 좋아하고 매개변수에 여러분이 처리할 수 있는 bash 변수를 할당하겠습니다.

#!/bin/bash

# fill 'line' with example content
line='0   22  * * 1-5 echo foo  bar   baz -o outfile.txt *'

# split 'line' into "scheduling" and "command" part:
SCHED=$(awk '{match($0, "^([0-9* -]*)([[:print:]]*)", a); print a[1]}' <<< "$line")
echo "$SCHED"
CMD=$(awk '{match($0, "^([0-9* -]*)([[:print:]]*)", a); print a[2]}' <<< "$line")
echo  "$CMD"

이것을 테스트하면 다음과 같이 출력되어야 합니다.

user@host $ ./split_test.sh 
0   22  * * 1-5 
echo foo  bar   baz -o outfile.txt *

설명하다

  • 실제 "분할"을 수행하는 두 줄에서 왼쪽의 변수를 $( ... )해당 섹션의 명령 출력에 할당합니다(예:고급 Bash 스크립팅 가이드예를 들어) 변수의 내용을 입력하는 경우 $line이중 괄호( ' )를 통한 와일드카드를 방지합니다(공백은 "있는 그대로" 유지됩니다)." ... "awk
  • awk호출은 내부 match()함수를 사용하여 문자열에서 특정 패턴을 찾습니다. 우리의 경우 ( ... )숫자, 별표, 공백 및 대시의 조합을 포함하는 줄 시작 부분의 집합과 인쇄 가능한 문자를 포함하는 집합이 뒤따릅니다. 수량은 제한되지 않습니다. 정규식은 욕심이 많기 때문에 두 부분 모두 가능한 가장 긴 하위 문자열로 일치하므로 그룹 1은 ./맞지 않는 첫 번째 문자(예: 첫 번째 영숫자 문자라도)를 찾을 때까지 실제로 계속됩니다. 두 번째 그룹은 단순히 줄의 나머지 부분이며 숫자와 특수 문자를 포함하여 인쇄 가능한 모든 문자를 포함할 수 있습니다.
  • awks 함수를 사용하는 match이유는 하위 그룹을 괄호로 묶어 지정하면 awk패턴의 실제 값, 이 경우 그룹 1에 포함된 실제 값 a으로 배열이 채워지도록 지시할 수 있다는 것입니다. a[1](" a[2]그룹 2(" 명령" 섹션) 및 그룹 2(" 명령" 섹션)의 실제 값입니다 .
  • 약간 우아하지 않지만 이를 두 번 적용하여 awk첫 번째 호출에서 첫 번째 부분을 출력하고 두 번째 호출에서 두 번째 부분을 출력하여 별도의 bash 변수에 값을 할당합니다.

이에 대해 더 알고 싶다면 살펴보십시오.GNU Awk 사용자 가이드.

답변4

다음과 같이 cut을 사용하여 공백으로 구분된 값을 구분할 수 있습니다.

#/bin/sh

var='0 22 * * 1-5 echo hello'

first=$(echo -n "$var" | cut -d' ' -f1)
second=$(echo -n "$var" | cut -d' ' -f2)
third=$(echo -n "$var" | cut -d' ' -f3)
fourth=$(echo -n "$var" | cut -d' ' -f4)
fifth=$(echo -n "$var" | cut -d' ' -f5)

restofvar=$(echo -n "$var" | cut -d' ' -f6,7)

E: 주석에서 지적했듯이 문자열에 공백이 여러 개 있는 경우 단일 공백으로 바꿔야 합니다.

var=$(echo "$var" | tr -s " ")

관련 정보