Команда для печати только последних 3 символов строки

Дистрибутив Linux состоит из многих частей. Всем частям, которые основаны на программном обеспечении, лицензируемом под GPL GNU и другими разрешенными для копирования лицензиями, нужно было выпустить источник кода. Например, если Вы поставляете что-то, основывался на ядре Linux, необходимо обеспечить источник ядра Linux, а также любой патч, который Вы сделали к источнику ядра (однако, для ядра Linux, Linus Torvalds интерпретирует GPL как не требующий для обеспечения исходного кода для кода, который только загружается как модуль). Можно поставить исходный код на CD или предложить тот, люди загружают его с веб-сайта или любого другого разумного метода.

Вы не должны обеспечивать исходный код для non-GPL программ, которые включены в ту же систему. Большинство дистрибутивов (Red Hat, SuSE, Ubuntu, даже Debian ¹) предоставляет некоторое небесплатное программное обеспечение в двоичной форме только.

Существуют другие варианты Unix, которые не только не требуют открытого лицензирования никакого базового компонента, но даже запрещают его. Конечно, оборот - то, что необходимо будет заплатить для лицензирования их. Они имеют тенденцию работать в большой области сервера, не во встроенной области: Солярис, AIX, HP-UX, SCO... IOS Apple работает на том, что иногда называют высокопроизводительной встроенной системой (MP3-плееры, мобильные телефоны), но они - исключительно аппаратные средства Apple, Вы не сможете лицензировать ОС.

Существуют также варианты Unix, лицензируемые в соответствии с лицензией BSD. Лицензия BSD позволяет Вам делать в значительной степени, что Вы хотите с ними только с условием, что Вы подтверждаете, что существует некоторое BSD-лицензированное программное обеспечение внутри (детали требования подтверждения зависят от версии лицензии). Существует несколько дистрибутивов Unix, где целая базовая система обеспечивается в соответствии с лицензией BSD: FreeBSD, OpenBSD, NetBSD являются основными. Обратите внимание, что некоторые компоненты имеют различные лицензии; в частности, компилятор C является GCC, который находится под GPL GNU (Вы, вероятно, не поставили бы компилятор однако).

Для встроенной системы MINIX, более вероятно, будет соответствующим. Это опубликовано в соответствии с лицензией BSD и разработано и для обучения и для встроенных систем.

Главное преимущество Linux состоит в том, что он имеет драйверы для примерно любой системы, которую можно найти. Дело обстоит не так с другими нельдами. Даже для MINIX, Вам придется, вероятно, записать набор драйверов.

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

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

30
22.10.2014, 02:04
11 ответов

Почему никто не дал очевидного ответа?

sed 's/.*\(...\)/\1/'

... или чуть менее очевидного

grep -o '...$'

Признаю, что второй имеет недостаток что строки с менее чем тремя символами исчезают; но вопрос явно не определял поведение в этом случае.

52
27.01.2020, 19:38

Если строка находится в переменной, вы можете сделать:

printf %s\\n "${var#"${var%???}"}"

, которая покладывает последние три символа из значения $ var , как:

${var%???}

... а затем полоски от головы $ var Все , но Что было только что уделить:

${var#"${var%???}"}

Этот метод имеет свои выделения и недостатки. На светлой стороне он полностью портативный POSIX и должен работать в любой современной оболочке. Кроме того, если $ var не содержит не менее трех символов Ничего , но тянутся \ N EWLINE. Опять же, если вы хотите , он напечатан в этом случае, вам нужен дополнительный шаг, как:

last3=${var#"${var%???}"}
printf %s\\n "${last3:-$var}"

таким образом $ Last3 , только когда-либо пустым, если $ var Содержит 3 или меньше байтов. И $ var когда-либо заменит только $ HAST3 , если $ Last3 пустой или unset - и мы знаем, что это не unset , потому что мы просто установили его.

11
27.01.2020, 19:38

Вы можете сделать это, но это немного ... чрезмерно:

for s in unlimited 987654 123456789; do
    rev <<< $s | cut -c 1-3 | rev
done 
ted
654
789
7
27.01.2020, 19:38

Использование awk :

awk '{ print substr( $0, length($0) - 2, length($0) ) }' file
ted
654
789
13
27.01.2020, 19:38

Если ваш текст находится в переменную оболочки под названием String , вы можете сделать это в Bash , ZSH или MKSH Shell:

printf '%s\n' "${STRING:(-3)}"

или

printf '%s\n' "${STRING: -3}"

, которые также имеют преимущество для работы с KSH93, от которого приступает синтаксис.

Точка заключается в том, что : должен быть отделен от - , в противном случае он становится $ {var: -Default} Оператор Борна оболочка.

Эквивалентный синтаксис в ZSH или yash оболочки:

printf '%s\n' "${STRING[-3,-1]}"
36
27.01.2020, 19:38

Проще говоря - tail

Нам не нужно регулярное выражение или более одного процесса только для подсчета символов.
​​ Команда tail , часто используемая для отображения последних строк файла, имеет параметр -c ( --bytes ), который кажется как раз подходящим инструментом для этого:

$ printf 123456789 | tail -c 3
789

(Когда вы находитесь в оболочке, имеет смысл использовать метод, подобный ответу mikeserv, потому что он экономит запуск процесса для хвоста .)

Настоящие символы Юникода?

Теперь вы запрашиваете последние три символа ; Это не то, что дает вам этот ответ: он выводит последние три байта !

Пока каждый символ состоит из одного байта, tail -c просто работает. Таким образом, его можно использовать, если набор символов - ASCII , ISO 8859-1 или вариант.

Если у вас есть ввод Unicode, например, в общем формате UTF-8 , результат неверен:

$ printf 123αβγ | tail -c 3
�γ

В этом примере, используя UTF-8 , греческие символы Альфа, бета и гамма состоят из двух байтов:

$ printf 123αβγ | wc -c  
9

Параметр -m может, по крайней мере, подсчитать реальные символы Юникода:

printf 123αβγ | wc -m
6

Хорошо, последние 6 байтов дадут нам последние 3 символа:

$ printf 123αβγ | tail -c 6
αβγ

Итак, tail не поддерживает обработку общих символов и даже не пытается (см. Ниже): он обрабатывает строки переменного размера, но не символы переменного размера.

Скажем так: tail как раз подходит для структуры задачи, которую нужно решить, но неверно для типа данных.

GNU coreutils

Если посмотреть дальше, выясняется, что это GNU coreutils, набор основных инструментов, таких как sed , ls , tail и разрез , еще не полностью интернационализирован. В основном это касается поддержки Unicode.
Например, cut будет хорошим кандидатом для использования вместо хвоста здесь для поддержки персонажа; У него есть опции для работы с байтами или символами, -c ( - bytes ) и -m ( - chars ) ;

Только -m / - chars , начиная с версии
вырезано (GNU coreutils) 8.21 , 2013,
{{1} }не реализованы!

Из вырезать информацию :

`-c CHARACTER-LIST'
`--characters=CHARACTER-LIST'
     Select for printing only the characters in positions listed in CHARACTER-LIST.  
     The same as `-b' for now, but internationalization will change that.


См. Также этот ответ с на Невозможно использовать `cut -c` (` --characters`) с UTF-8? .

43
27.01.2020, 19:38

Пуленепробиваемое решение для строк utf-8:

utf8_str=$'\xd0\xbf\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82' # привет

last_three_chars=$(perl -CAO -e 'print substr($ARGV[0], -3)' "$utf8_str")

Или используйте:

last_three_chars=$(perl -MEncode -CO -e '
  print substr(decode("UTF-8", $ARGV[0], Encode::FB_CROAK), -3)
' "$utf8_str")

для предотвращения неправильная обработка данных.

Пример:

perl -MEncode -CO -e '
  print substr(decode("UTF-8", $ARGV[0], Encode::FB_CROAK), -3)
' $'\xd0\xd2\xc9\xd7\xc5\xd4' # koi8-r привет

Выводит примерно следующее:

utf8 "\xD0" does not map to Unicode at /usr/lib/x86_64-linux-gnu/perl/5.20/Encode.pm line 175.

Не зависит от настроек локали (т.е. работает с LC_ALL = C ). Bash , sed , grep , awk , rev требуют что-то вроде этого: LC_ALL = en_US .UTF-8

Общее решение:

  • Получить байты
  • Определить кодировку
  • Расшифровать байты в символы
  • Извлечь символы
  • Кодировать символ в байты

Вы можете определить кодировку с помощью uchardet . См. Также связанные проекты .

Вы можете декодировать / кодировать с помощью Encode в Perl, кодеков в Python 2.7

Пример :

Извлечь последние три символа из строки utf-16le и преобразовать эти символы в utf-8

utf16_le_str=$'\xff\xfe\x3f\x04\x40\x04\x38\x04\x32\x04\x35\x04\x42\x04' # привет

chardet <<<"$utf16_le_str"  # outputs <stdin>: UTF-16LE with confidence 1.0

last_three_utf8_chars=$(perl -MEncode -e '
    my $chars = decode("utf-16le", $ARGV[0]);
    my $last_three_chars = substr($chars, -3);
    my $bytes = encode("utf-8", $last_three_chars);
    print $bytes;
  ' "$utf16_le_str"
)

См. также: perlunitut , Python 2 Unicode HOWTO

3
27.01.2020, 19:38

Получить размер строки с помощью:

size=${#STRING}

Затем получить подстроку из последних n символов:

echo ${STRING:size-n:size}

Например:

STRING=123456789
n=3
size=${#STRING}
echo ${STRING:size-n:size}

даст:

789
0
27.01.2020, 19:38

Как насчет использования «expr» или «rev»?

Ответ, аналогичный тому, который дал @ G-Man : expr "$ yourstring": '. * \ (. .. \) $ ' У него тот же недостаток, что и у решения grep.

Хорошо известный трюк - комбинировать «вырезать» с «оборотом»: echo «$ yourstring» | rev | cut -n 1-3 | rev

1
27.01.2020, 19:38

printf не будет работать, если в строке есть пробелы.

Код ниже для строки с пробелом

str="Welcome to Linux"
echo -n $str | tail -c 3

nux

-1
27.01.2020, 19:38

хвост -n 1 ревизии.log | awk '{ print substr ($0, 0, length ($0 )-(length ($0 )-13 ))}'

Если вы хотите напечатать первые тринадцать символов с начала

0
27.01.2020, 19:38

Теги

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