Команда Linux (як кішка) для читання заданої кількості символів


120

Чи є така команда, як catу Linux, яка може повернути задану кількість символів з файлу?

наприклад, у мене є текстовий файл на зразок:

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"що втрачено назавжди.
Єті

Відповіді:


192

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і використовуйте хвіст, щоб отримати останні 100:

head -c 200 file | tail -c 100

@Miffy: Прочитайте перші 20 байт head, а потім скористайтеся tailдля отримання останніх 10, наприклад:head -c 20 file | tail -c 10
День

47

Ви можете використовувати 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

2
Я б рекомендував проти цього рішення взагалі, оскільки dd bs=1змушує дд читати і писати по одному символу за один раз, що набагато повільніше, ніж headколи велика кількість. Однак це не помітно для підрахунку = 5.
ефеміент

2
Що щодо "dd count = 1 bs = 5"? Це дозволило б голові прочитати п'ять байтів за один рух. Все-таки голова - це, мабуть, більш чітке рішення.
Бен Комбі

1
Дякую за це - я насправді шукав спосіб «вирізати» двійковий файл, і dd, схоже, зробить трюк .. Привіт!
sdaau

це був рятувальник head -cdd bs=5 count=1
живих наборів

11

голова :

Ім'я

head - виведення першої частини файлів

Конспект

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

Опис

Друкуйте перші 10 рядків кожного ФАЙЛУ до стандартного виводу. Маючи більше ніж один ФАЙЛ, передуйте кожному із заголовків із зазначенням назви файла. Якщо файл FILE відсутній, або коли FILE -, прочитайте стандартний ввід.

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


3

голова або хвіст також можуть це зробити:

голова -c X

Друкує перші X байти (не обов'язково символи, якщо це файл UTF-16) цього файлу. хвіст зробить те саме, за винятком останніх X байтів.

Цей (і вирізаний) портативний.


3
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використовується для вибору останнього рядка, відображеного головою.


2

ви також можете відрізати лінію, а потім вирізати її, як, наприклад:

grep 'текстове' ім'я файлу | вирізати -c 1-5


Це не працює, якщо вхідний файл - це нескінченний потік, що не має \ n
Ajay Brahmakshatriya

2

Я знаю, що відповідь відповідає на запитання, яке було задано 6 років тому ...

Але я шукав щось подібне протягом декількох годин, а потім з’ясував, що: cut -c робить саме це, з додатковим бонусом, що ви також можете вказати компенсацію.

cut -c 1-5 повернеться Привіт, а cut -c 7-11 поверне світ . Не потрібно ніякої іншої команди


2
Ваше право!. Я просто хотів виділити можливість більш загальної команди, яка може повернути текст із середини файлу, на відміну від head -c буде читати лише початкові символи, хвіст -c останні символи. І без використання grep :).
Боббіс

2

Навіть незважаючи на те, що відповідь на цю відповідь / прийнято ще багато років тому, прийнята на даний момент відповідь є правильною лише для кодування однобайтових символів на зразок 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:]'
π

Ще одна нещодавня відповідь вже запропонувала "вирізати", але лише через побічну проблему, яку можна використовувати для вказівки довільних зрушень, а не через безпосередньо відповідні символи проти байтів.

Якщо ваша 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

згідно з он-лайн документацією, вона ще недоступна: "Виберіть для друку лише символи на позиціях, зазначених у списку символів. Те саме, що і -b на даний момент, але інтернаціоналізація змінить це." [ gnu.org/software/coreutils/manual/html_node/…
LEo

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

0

Ось простий сценарій, який завершується з використанням ddпідходу, згаданого тут:

extra_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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.