항목에 줄 바꿈을 삽입하는 방법은 무엇입니까?

항목에 줄 바꿈을 삽입하는 방법은 무엇입니까?

탭으로 구분된 파일 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                 
-----------------------------------------------------------

관련 정보