탭으로 구분된 파일 test1.txt에 다음 항목이 있습니다.
key1 10|15 20 30 11|xx 21 31
key2 527|240 269 0 0 0 2462 546 281 0 0
이 파일을 다음 형식으로 변환할 수 있는 방법이 있습니까? 파이프로 구분된 값을 다음 줄로 옮기고 싶습니다. 파이프의 개수에는 제한이 없으며, 파이프로 구분된 값의 문자 개수는 동일해야 합니다.
key1 10 20 30 11 21 31
key1 15 xx
key2 527 269 0 0 0 2462 546 281 0 0
key2 240
답변1
내 스크립트는 구분 기호로 구분된 두 값의 문자 수가 동일한 경우 작동합니다.
임의의 수의 공백을 원하는 경우 다음과 같은 결과가 나올 수 있으므로 일반적으로 불가능합니다.
key1 12|1222 10|15
key1 12 10
key1 1222 15
이 경우 해당 열은 이미 "1222"로 채워져 있으므로 "15"를 "10" 아래의 열에 정렬할 수 없습니다.
편집하다:나는 코드를 다시 작성하여 원하는 수의 라인과 원하는 수의 파이프를 사용합니다 :-)
암호:
스크립트.sh:
#!/bin/bash
# count max number of pipes -> recognizes number of lines
countPipes() {
num=0
line="$@"
IFS=' '
for item in $line; do
tmp=$(echo "$item" | tr -d "[:alnum:][:space:]" | wc -c)
if [[ "$num" < "$tmp" ]]; then
num=$tmp
fi
done
return $num
}
makeLines() {
strTmp="$@" # one line from input file
arrTmp=($strTmp)
key=${arrTmp[0]}
arrIN=$key
# create output arrays (one array = one output line)
countPipes $strTmp
maxPipeCount=$? # assign the value of the last 'return'
for((i=0;i<$maxPipeCount;++i)); do
arrOUT[$i]="$key"
done
for item in ${strTmp[@]}; do
# Delimiter handling
if [[ $item == *\|* ]]; then # If there is a pipe
IFS='|'
tmp=($item) # variable containing pipe character -> split by space -> array
IFS=' '
arrIN="$arrIN ${tmp[0]}"
for ((i=0;i<"${#arrOUT[@]}";++i)); do # fill columns in every output line - i = index in line
if [[ "${#tmp[$(($i + 1))]}" -gt 0 ]]; then
arrOUT[$i]="${arrOUT[$i]} ${tmp[$(($i + 1))]}"
else
# Handling spaces in output
for ((j=0;j<="${#tmp[0]}";++j)); do # filling line with spaces - j = just counter, not index
arrOUT[$i]="${arrOUT[$i]} "
done
fi
done
elif [[ "$item" != "$key" ]]; then # If there isn't a pipe
arrIN="$arrIN $item"
# Handling spaces in output
for ((i=0;i<"${#arrOUT[@]}";++i)); do # for every output line
for j in { 1.."${#tmp[0]}" }; do # for every char in $item
arrOUT[$i]="${arrOUT[$i]} "
done
done
fi
done
# PRINT RESULTS
echo "$arrIN"
for((i=0;i<"${#arrOUT[@]}";++i)); do # for every output line
echo "${arrOUT[$i]}"
done
unset arrOUT
echo '-----------------------------------------------------------'
}
while read line; do # load data from STDIN
makeLines $line
done
예:
테스트.txt:
key1 10|15 20 30 11|XX|55 21 31|20 100
key2 11 25|30 58|22 44 33
key3 12|15|17|19 22 33 55|22 88|44|11 xxxx|2222|7777
주문하다:
bash ./script.sh < test.txt
산출:
key1 10 20 30 11 21 31 100
key1 15 XX 20
key1 55
-----------------------------------------------------------
key2 11 25 58 44 33
key2 30 22
-----------------------------------------------------------
key3 12 22 33 55 88 xxxx
key3 15 22 44 2222
key3 17 11 7777
key3 19
-----------------------------------------------------------