Как отрезать линии, длина которых превышает некоторую ширину, и обозначить линии, которые были отрублены с помощью многоточия?
Следует отмечать только строки, которые были фактически сокращены, но не строки, которые только что правая длина в первую очередь.
Я хотел бы использовать команду в конвейере.
Попробуйте следующее:
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'
Некоторые возможности:
с sedsed -E 's/(.{N})(.{1,})$/\1.../' file
несколько более элегантно с perl (с использованием lookbehind) perl -pe 's/(?<=.{N}).{1,}$/.../' file
, где N - количество символов, после которых вы хотите заменить на многоточие.
awk, sed и perl, как представлено в других ответах, превосходят при обработке текста и, вероятно, являются лучшими инструментами для работы.
Но вы также можете это сделать в чистом awk (т. е. «без выхода из оболочки»), если вам нравится:
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 ;}
(Эта версия, заключенная в скобки, также отлично работает в других контекстах, в том числе с перенаправлением, как указано выше. Скобки не нужны в этом случае, но не вредны.) [ ! d12]
Это выглядит так:
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