Команда Linux (например, cat) для чтения указанного количества символов

Есть ли в Linux такая команда, как cat, которая может возвращать указанное количество символов из файла?

например, у меня есть текстовый файл, например:

Hello world
this is the second line
this is the third line

И мне нужно что-то, что возвращало бы первые 5 символов, то есть «привет».

Благодарность

Обратите внимание, что ни один из приведенных ответов не потребляет только N байтов из потока. Например: mkfifo /tmp/test.fifo; echo "hello world">/tmp/test.fifo & head -c 5 /tmp/test.fifo также потребляет " world\n", который утерян навсегда.

Yeti 22.07.2018 13:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
123
1
133 712
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

голова:

Имя

head - выводить первую часть файлов

Синопсис

голова [ВАРИАНТ] ... [ФАЙЛ] ...

Описание

Выведите первые 10 строк каждого ФАЙЛА на стандартный вывод. При наличии нескольких ФАЙЛОВ перед каждым должен стоять заголовок с именем файла. Без ФАЙЛА или когда ФАЙЛ -, читать стандартный ввод.

Обязательные аргументы для длинных опций являются обязательными и для коротких опций.
-c, - байты = [-] N распечатать первые N байтов каждого файла; с ведущим '-', вывести все, кроме последних N байтов каждого файла

голова или хвост тоже могут это сделать:

head -c X

Печатает первые X байтов (не обязательно символы, если это файл UTF-16) файла. tail будет делать то же самое, за исключением последних X байтов.

Это (и вырезано) портативны.

Ответ принят как подходящий

head тоже работает:

head -c 100 file  # returns the first 100 bytes in the file

... извлечет первые 100 байтов и вернет их.

Что хорошо в использовании head для этого, так это то, что синтаксис для tail совпадает:

tail -c 100 file  # returns the last 100 bytes in the file

Вы можете комбинировать их, чтобы получить диапазоны байтов. Например, чтобы получить 100 байтов второй из файла, прочтите первые 200 байтов с помощью head и используйте tail для получения последних 100:

head -c 200 file | tail -c 100

@Miffy: прочтите первые 20 байтов с помощью head, затем используйте tail для получения последних 10, например: head -c 20 file | tail -c 10

Dan 19.04.2020 03:44

вы также можете удалить строку, а затем вырезать ее, например:

grep 'text' имя файла | вырезать -c 1-5

Это не работает, если входной файл представляет собой бесконечный поток без \ n

Ajay Brahmakshatriya 25.10.2018 02:07

Вы можете использовать dd для извлечения произвольных блоков байтов.

Например,

dd skip=1234 count=5 bs=1

скопирует байты с 1235 по 1239 со своего входа на свой выход, а остальные отбросит.

Чтобы просто получить первые пять байтов из стандартного ввода, выполните:

dd count=5 bs=1

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

dd count=5 bs=1 if=filename

Также обратите внимание, что dd подробно сообщает о том, что он сделал, поэтому, чтобы выбросить это, выполните:

dd count=5 bs=1 2>&-

или же

dd count=5 bs=1 2>/dev/null

Я бы не рекомендовал это решение в целом, поскольку dd bs=1 заставляет dd читать и записывать по одному символу за раз, что намного медленнее, чем head, когда счетчик большой. Однако для count = 5 это не заметно.

ephemient 20.10.2008 21:45

А как насчет "dd count = 1 bs = 5"? Это заставило бы голову прочитать пять байтов за один раз. Тем не менее, голова, вероятно, более ясное решение.

Ben Combee 21.10.2008 02:14

Спасибо за это - я действительно искал способ "вырезать" бинарный файл, и dd, похоже, сработает .. Ура!

sdaau 15.11.2010 00:27

это была палочка-выручалочка на busybox без реализации head -c подход dd bs=5 count=1 работал

Jay Paroline 18.12.2016 11:07
head -Line_number file_name | tail -1 |cut -c Num_of_chars

этот скрипт дает точное количество символов из конкретной строки и местоположения, например:

head -5 tst.txt | tail -1 |cut -c 5-8

дает символы в строке 5 и символы с 5 по 8 в строке 5,

Примечание: tail -1 используется для выбора последней строки, отображаемой головой.

Я знаю, что ответ на вопрос, заданный 6 лет назад ...

Но я несколько часов искал нечто подобное, а потом обнаружил, что: вырезать -c делает именно это, с дополнительным бонусом, который вы также можете указать смещение.

вырезать -c 1-5 вернет Привет, а вырезать -c 7-11 вернет Мир. Нет необходимости в какой-либо другой команде

Твое право!. Я просто хотел подчеркнуть возможность более общей одиночной команды, которая может возвращать текст из середины файла, в отличие от head -c, который будет читать только начальные символы, tail -c - последние символы. И без использования grep :).

bobbyus 29.10.2014 14:38

Несмотря на то, что на этот вопрос был дан ответ / принят много лет назад, принятый в настоящее время ответ верен только для однобайтовых кодировок на символ, таких как iso-8859-1, или для однобайтовых подмножеств наборов символов с переменным байтом (например, латинские символы в UTF-8). Даже использование вместо этого многобайтовых соединений будет работать только для фиксированных многобайтовых кодировок, таких как UTF-16. Учитывая, что теперь UTF-8 находится на пути к тому, чтобы стать универсальным стандартом, и, глядя на этот список языков по количеству носителей языка и этот список из 30 лучших языков по родному / вторичному использованию, важно указать на простую технику, дружественную к переменным байтам (не основанную на байтах), с использованием cut -c и tr / sed с классами символов.

Сравните следующее, которое вдвойне терпит неудачу из-за двух распространенных латино-ориентированных ошибок / предположений относительно проблемы байтов и символов (один - head против cut, другой - [a-z][A-Z] против [:upper:][:lower:]):

$ printf 'Πού μπορώ να μάθω σανσκριτικά;\n' | \
$     head -c 1 | \
$     sed -e 's/[A-Z]/[a-z]/g'
[[unreadable binary mess, or nothing if the terminal filtered it]]

к этому (примечание: это отлично работало на FreeBSD, но как cut, так и tr на GNU / Linux по-прежнему искажали греческий язык в UTF-8 для меня):

$ printf 'Πού μπορώ να μάθω σανσκριτικά;\n' | \
$     cut -c 1 | \
$     tr '[:upper:]' '[:lower:]'
π

Another more recent answer had already proposed "cut", but only because of the side issue that it can be used to specify arbitrary offsets, not because of the directly relevant character vs. bytes issue.

Если ваш cut неправильно обрабатывает -c с кодировкой переменных байтов, для «первых символов X» (замените X своим номером) вы можете попробовать:

  • sed -E -e '1 s/^(.{X}).*$/\1/' -e q - хотя и ограничен первой строкой
  • head -n 1 | grep -E -o '^.{X}' - который ограничен первой строкой и связывает две команды, хотя
  • dd - который уже предлагался в других ответах, но действительно громоздкий
  • Сложный сценарий sed со скользящим оконным буфером для обработки символов, распределенных по нескольким строкам, но это, вероятно, более громоздко / хрупко, чем просто использовать что-то вроде dd.

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

  • sed -E -e 's/[[:upper:]]/\L&/g (для GNU)

извините, но здесь это не работает ... printf 'Πού ' | cut -c 1 просто возвращает тарабарщину ... он ведет себя как 'голова'

LEo 09.04.2018 21:41

согласно интерактивной документации, он пока недоступен: «Выберите для печати только символы в позициях, перечисленных в списке символов. То же, что и -b, но интернационализация изменит это». [gnu.org/software/coreutils/manual/html_node/…

LEo 09.04.2018 22:00

@LEo Судя по ссылке в вашем втором комментарии, кажется, что вы используете ОС на основе GNU, предположительно GNU / Linux, так что в этом случае это ожидается - я упоминаю об этом в конце своего ответа. Тогда он работал (и работает сейчас) для меня на FreeBSD (и, вероятно, в некоторых других ОС), но не работал (и еще не работал) на GNU / Linux, в этом случае я упомянул альтернативные методы в конце. Я лично не могу дождаться, пока кто-нибудь найдет и добровольно выделит свободное время для интернационализации, необходимой для того, чтобы набор инструментов GNU работал так же хорошо, как и другие в этом отношении.

rowanthorpe 11.04.2018 02:45

Вот простой сценарий, использующий упомянутый здесь подход dd:

extract_chars.sh

#!/usr/bin/env bash

function show_help()
{
  IT = "
extracts characters X to Y from stdin or FILE
usage: X Y {FILE}

e.g. 

2 10 /tmp/it     => extract chars 2-10 from /tmp/it
EOF
  "
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

FROM=$1
TO=$2
COUNT=`expr $TO - $FROM + 1`

if [ -z "$3" ]
then
  dd skip=$FROM count=$COUNT bs=1 2>/dev/null
else
  dd skip=$FROM count=$COUNT bs=1 if=$3 2>/dev/null 
fi

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