대부분의 경우 다음과 같은 입력 파일을 얻습니다.
java-1.8.0-openjdk.x86_64 1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
java-1.8.0-openjdk-headless.x86_64 1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
kernel.x86_64 2.6.32-754.23.1.el6 asyum:ol6_latest
...while 루프가 있고 다음 코드를 사용하여 각 행에 대해 field1과 field2를 성공적으로 캡처할 수 있습니다.
f1=$(echo $line | awk '{print $1}')
f2=$(echo $line | awk '{print $2}')
그러나 때때로 다음과 유사한 입력 파일이 표시됩니다.
java-1.8.0-openjdk.x86_64 1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
java-1.8.0-openjdk-headless.x86_64
1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
kernel.x86_64 2.6.32-754.23.1.el6 asyum:ol6_latest
(라인 2를 구분하는 추가 줄바꿈이 있다는 점에 유의하세요.)
이러한 유형의 입력을 프로그래밍 방식으로 처리하기 위한 팁/요령이 있습니까(입력 파일을 수동으로 정리하는 대신)?
답변1
다음은 선행 공백에만 의존하는 솔루션입니다. 예상되는 필드 수에 의존하지 않습니다.
이것GNU 매뉴얼sed
"공백으로 시작하는 줄을 연결하는" 방법을 제공합니다.
sed -E ':a ; $!N ; s/\n\s+/ / ; ta ; P ; D'
매뉴얼에서는 이식 가능한(GNU가 아닌) 변형이 다음과 같다고 주장합니다.
sed -e :a -e '$!N;s/\n */ /;ta' -e 'P;D'
답변2
이렇게 하면 원하는 효과를 얻을 수 있습니다.
#!/usr/bin/env bash
while read line; do
declare -a array=($line)
if test ${#array[@]} != 3; then
read line2
array+=($line2)
fi
f1=${array[0]}
f2=${array[1]}
echo $f1 $f2
done
run with : test.sh < inputfile
행에 세 개의 항목이 포함되어 있는지 확인하고 그렇지 않은 경우 다음 행을 조인합니다.
답변3
어쨌든 그것을 사용하고 있으니 awk
전적으로 의존하는 것은 어떨까요? 노력하다
read f1 f2 <<< $(awk '{while (NF < 3) {getline X; $0 = $0 FS X}; print $1, $2}' file)
답변4
입력 데이터의 올바른 형식의 각 행이 세 단어(여기서는 공백 문자를 포함하지 않는 문자열로 느슨하게 정의됨)로 구성된다고 가정하면 입력 데이터를 전처리할 수 있습니다.
<input_file tr -s '[:blank:]' '\n' | paste - - - | column -t
<newline>
여기서는 모든 공백 문자(문자 포함)를 단일 로 바꾸고 <newline>
, 결과를 세 단어 줄로 재배치하고, 출력 형식을 깔끔하게 지정합니다. 마지막 단계는 귀하의 질문을 고려할 때 불필요한 장식 단계입니다.