Bash에서 grep 출력 분할

Bash에서 grep 출력 분할

grep파일의 마지막 줄을 얻기 위해 파이프를 사용하여 bash에서 텍스트 줄을 읽은 다음 tail줄의 처음 세 "단어"(예: 공백을 사용하여 구분)를 배열 요소로 분할하려고 합니다.

출력의 요소를 반복하려고 하면 for제대로 작동하고 원하는 요소 목록을 얻습니다.

[] foo=$(grep select file.txt | tail -n 1)
[] echo $foo
0.47331 5.11188 13.1615 # select

[] for x in $foo; do echo $x; done
0.47331
5.11188
13.1615
#
select

그것이 바로 내가 하고 싶은 일이다!

그러나 처음 세 요소가 포함된 배열을 꺼내려고 하면 foo작동하지 않습니다.

[] echo "${foo[@]:0:2}"
0.47331 5.11188 13.1615 # select 4.95294 13.5177

특히 이상한 점은 줄 끝의 마지막 두 값이 실제로는첫 번째selectfile.txtin (행의 처음 두 항목이 아니라 두 번째와 세 번째 항목!)을 포함하는 행 이므로 전혀 foo포함 되어서는 안 됩니다.

마찬가지로 단순히 "단어"를 잘라내려고 하면 foo이상한 결과가 나옵니다.

[] echo "${foo[0]}"
0.47331 5.11188 13.1615 # select

[] echo "${foo[1]}"
4.95294

(또 마지막 값은 있어서는 안되는 값인데, 제가 아는 한 에 있어도 foo첫 번째 행의 두 번째 항목입니다 select... file.txt).

무슨 일이 일어나고 있는지, 내가 원하는 출력(배열)을 얻는 방법을 이해해야 합니다 0.47331 5.11188 13.1615.

답변1

$foo배열이 아니라 공백으로 구분된 여러 단어를 포함하는 문자열입니다. 배열이 되도록 하려면 다음과 같이 지정하십시오.

foo=( $(grep 'select' file.txt | tail -n 1) )

${foo[0]}이제 또는 처음 세 요소를 로 참조할 수 있습니다 ${foo[@]:0:3}.

${foo[@]}여기에는 처음 세 개의 요소만 추출할 수 있는 것이 없기 때문에 여기에는 마지막 일치 행의 다섯 개 요소가 모두 포함 됩니다 . 원하는 경우 크기에 맞게 foo=("${foo[@]:0:3}")잘라서 사용할 수 있습니다.${foo[@]}

또는 처음 세 요소만 포함하는 배열을 만들려면 awk다음과 같이 사용할 수 있습니다.

foo=( $(awk '/select/ { a=$1; b=$2; c=$3 } END { print a,b,c }' file.txt) )

답변2

이렇게 하면 데이터를 변수로 읽는 것을 방지할 수 있습니다.

$ grep -F select file | tail -n 1 | cut -d ' ' -f 1-3
0.47331 5.11188 13.1615

의 배열에 값을 넣으려면 (또는 )을 bash사용하십시오 .mapfilereadarray

$ mapfile -t arr < <( grep -F select file | tail -n 1 | cut -d ' ' -f 1-3 | tr ' ' '\n' )
$ printf 'arr: %s\n' "${arr[@]}"
arr: 0.47331
arr: 5.11188
arr: 13.1615

나는 tr숫자 사이의 공백을 줄 바꿈으로 변경하는 데 사용합니다. 이렇게 하면 배열의 마지막 값 끝에 후행 개행 문자가 없어집니다.


어색한 +++ 파이프 대신 grep분명히 사용할 tail수 있습니다cuttr

awk '/select/ { a=$1; b=$2; c=$3 } END { printf("%s\n%s\n%s\n", a, b, c) }'

또는 프로세스 교체와 유사한 것입니다 <(...).

관련 정보