Limitar linhas max e min length

3

Eu tenho esta entrada:

XX3083136|bla-bla texthere texttt|[email protected]|SADFdsafsafd|ASDfasfdsafd|DSFSAFD|dsafasfd|sadfsad|
XX3083372|bla-bla-bla this is a text bla-bla|[email protected]|SDFsafas|SADFsa|DFSsdf|asdasdf|sadfdsafsaf|asdfsadf|

e eu preciso dessa saída:

XX3083136|bla-bla texthere textt|[email protected]         |SADFdsafsafd|ASDfasfdsafd|DSFSAFD|dsafasfd|sadfsad|
XX3083372|bla-bla-bla this is a te|[email protected]      |SDFsafas|SADFsa|DFSsdf|asdasdf|sadfdsafsaf|asdfsadf|

Portanto, a diferença é que preciso controlar o tamanho máximo do texto entre "|". Se for mais curto, então o tamanho da linha deve ser "" aplicado. Neste exemplo, a segunda linha é limitada a um máximo de 24 caracteres e a terceira linha deve ter pelo menos 30 caracteres. Linhas diferentes precisarão de limites max / min diferentes.

Como posso fazer isso no bash?

    
por gasko peter 13.03.2013 / 13:19

2 respostas

3

Para complementar um pouco:

O formato básico para printf no texto é:

%s      # Print as is
%10     # Right justify minimum width print 10
%-10    # Left justify minimum width print 10
%.10    # Max width 10
%10.10  # Max width 10, min width print 10
%-10.10 # Left justify, max width 10, min width print 10
%*s     # Same as above, but get number from arguments
%-*s    # Same as above, but get number from arguments
...

Quando alguém obtém padrões longos, pode se tornar um pouco confuso para acompanhar onde e quais etc. Uma maneira de tornar isso um pouco mais fácil pode ser algo assim:

#!/bin/bash

usage()
{
    printf "Usage: %s <FILE>\n" "$(basename "$0")" >&2
    [[ -n "$1" ]] && echo "$1"
    exit 1
}

if [[ ! -t 0 ]]; then
    : # Piped to
elif [[ $# -eq 0 ]]; then
    usage "Missing file."
elif [[ ! -r "$1" ]]; then
    usage "Unable to read \'$1'."
else
    # Accept input from file to file descriptor 0, aka stdin
    exec 0< "$1"
fi

fmt=""
fmt="$fmt%s|"       # F1
fmt="$fmt%-24.24s|" # F2
fmt="$fmt%-30s|"    # F3
fmt="$fmt%-10.10s|" # F4
fmt="$fmt%-10.10s|" # F5
fmt="$fmt%-10s|"    # F6
fmt="$fmt%-2.2s|"   # F7
fmt="$fmt%-2.2s|\n" # F8

# Set IFS to newline and bar and read fields
# assigning them to f1 ... f8
#
while IFS=$'\n'"|" read f1 f2 f3 f4 f5 f6 f7 f8; do
    printf "$fmt"\
    "$f1" "$f2" "$f3" "$f4" \
    "$f5" "$f6" "$f7" "$f8"
done <&0

por exemplo:

while IFS=$'\n'"|" read f1 f2 f3 f4 f5 f6 f7 f8; do
    printf "%s|%-*.*s|%-*s\n" \
    "$f1" \
    24 24 "$f2" \
    30 "$f3"
done < "input"

Se for apenas análise de linha, o awk é uma boa alternativa. por exemplo:

#!/usr/bin/awk -f

BEGIN {FS="|"}
/^/ {
    printf "%s|%-24.24s|%-30s|%-10.10s|%-10.10s|%-10s\n",
        $1, $2, $3, $4, $5, $6
}

Ou:

#!/usr/bin/awk -f

BEGIN {
    FS="|"
}
/^/ {
    printf "%s|%-*.*s|%-*s|%-*.*s|%-*.*s|%-*s\n",
        $1,
        24, 24, $2,
        30, $3,
        10, 10, $4,
        10, 10, $5,
        10, $6
}
    
por 13.03.2013 / 16:46
2

Você pode reproduzir em torno de printf incorporado para cortar uma string:

$ printf '%.2s\n' 'azerty'
az

E usá-lo para colocar o delimitador | onde você quiser, ex:

$ printf '%10s%10s%10s%10s%10s%10s\n' '|' '|' '|' '|' '|' '|'
         |         |         |         |         |         |

Veja link

    
por 13.03.2013 / 13:26

Tags