Несмотря на то, что на этот вопрос был дан ответ / был принят несколько лет назад, принятый в настоящее время ответ верен только для однобайтовых кодировок на символ, таких как 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
(ГНУ-специфических)
mkfifo /tmp/test.fifo; echo "hello world">/tmp/test.fifo & head -c 5 /tmp/test.fifo
также потребляет то," world\n"
что потеряно навсегда.