Укоротить линии, добавив многоточие "..."

Как отрезать линии, которые длиннее некоторой ширины, и пометить отрезанные многоточием многоточие?

Должны быть отмечены только те линии, которые были фактически укорочены, но не те линии, которые изначально имели правильную длину.

Я хотел бы использовать команду в конвейере.

6 ответов

Решение

Это обрежет строку, отрежет дополнительные три символа и добавит "...", если длина больше значения, которое вы указали в качестве параметра.

other_programs | \
awk -v len=40 '{ if (length($0) > len) print substr($0, 1, len-3) "..."; else print; }'

Попробуй это:

awk -F '' '{if (NF > 70) {print substr($0, 0, 71)"..."} else print $0}'

Если NF слишком высока, проще:

awk '{if (length($0) > 70) {print substr($0, 0, 71)"..."} else print $0}'

или более короткая версия:

awk 'length > 70{$0=substr($0,0,71)"..."}1'

Некоторые возможности:

  • с седом

    sed -E 's/(.{N})(.{1,})$/\1.../' file
    
  • немного более элегантно с Perl (используя lookbehind)

    perl -pe 's/(?<=.{N}).{1,}$/.../' file
    

где N количество символов, после которого вы хотите заменить его многоточием.

awk, sed, а также perl, как представлено в других ответах, превосходен в обработке текста и, вероятно, является лучшим инструментом для работы.

Но вы также можете сделать это в чистом виде bash (т. е. "не выходя из оболочки"), если вам нравится:

n=70
while read -r; do
    if ((${#REPLY}<=n))
        then printf '%s\n' "$REPLY"
        else printf '%s...\n' "${REPLY:0:$((n-3))}"
    fi
done < filename

замещать 70с максимальной желаемой длиной, и filename с входным файлом.

Чтобы использовать это в правой части канала (т. Е. Передать в него выходные данные другой команды), удалите < filename и либо установить n заранее или приложить все это в { ... ;}:

{ n=70
while read -r; do
    if ((${#REPLY}<=n))
        then printf '%s\n' "$REPLY"
        else printf '%s...\n' "${REPLY:0:$((n-3))}"
    fi
done ;}

(Эта версия в квадратных скобках также отлично работает в других контекстах, в том числе с перенаправлением, как указано выше. В этом случае скобки не нужны, но не вредны.)

Это выглядит так:

ek@Ilex:~$ help read | head -5 | { n=70
> while read -r; do
>     if ((${#REPLY}<=n))
>         then printf '%s\n' "$REPLY"
>         else printf '%s...\n' "${REPLY:0:$((n-3))}"
>     fi
> done ;}
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N n...
    Read a line from the standard input and split it into fields.

    Reads a single line from the standard input, or from file descr...
    if the -u option is supplied.  The line is split into fields as...

Обратите внимание, что, как и в других решениях, которые были представлены до сих пор, это не позволит полностью ограничить ширину вывода при наличии символов, отображающих более одного столбца, например горизонтальных вкладок.

Другая perl решение:

perl -ple '$_ = sprintf "%.70s...", $_ if length > 70' file

Принятый ответ записывается в виде функции с примером, также помещая... в середине строки, а не в конце:

truncate() {    
    echo "$@" | \
    awk -v len=15 '{ if (length($0) > len) print substr($0, 1, len-3) "..." substr($0, length($0) - len, length($0)); else print; }'
}

пример:

parse_branch() {
    branch=$(git symbolic-ref --short HEAD || hg branch)
    truncate "$branch"
}
Другие вопросы по тегам