Сократите строки, добавив “…” замещающий знак

Как отключить строки, которые длиннее, чем некоторая ширина и маркировка строк, которые были обрублены с замещающим знаком?

Только строки, которые были на самом деле сокращены, должны быть отмечены, но не строки, которые имели просто правильную длину во-первых.

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

7
задан 14 September 2014 в 15:23

6 ответов

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

other_programs | \
awk -v len=40 '{ if (length($0) > len) print substr($0, 1, len-3) "..."; else print; }'
13
ответ дан 23 November 2019 в 06:09

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

  • с sed

    sed -E 's/(.{N})(.{1,})$/\1.../' file
    
  • немного более изящно с жемчугом (использующий lookbehind)

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

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

5
ответ дан 16 November 2019 в 18:18

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...

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

3
ответ дан 16 November 2019 в 18:18

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

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"
}
0
ответ дан 16 November 2019 в 18:18

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

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'
7
ответ дан 23 November 2019 в 06:09

Другой perl решение:

perl -ple '$_ = sprintf "%.70s...", $_ if length > 70' file
0
ответ дан 23 November 2019 в 06:09

Другие вопросы по тегам:

Похожие вопросы: