Linux命令(如cat)读取指定数量的字符


120

有没有像catlinux这样的命令可以从文件中返回指定数量的字符?

例如,我有一个文本文件,例如:

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

我想要的东西可以返回前5个字符,即“ hello”。

谢谢


请注意,所有给定的答案都不消耗流中的N个字节。例如:mkfifo /tmp/test.fifo; echo "hello world">/tmp/test.fifo & head -c 5 /tmp/test.fifo还消耗" world\n"永远丢失的东西。
雪人

Answers:


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个字节,请head使用读取前200个字节,然后使用tail来获取后100个字节:

head -c 200 file | tail -c 100

@Miffy:使用读取前20个字节head,然后使用tail获取后10 个字节,例如:head -c 20 file | tail -c 10
Dan

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强制dd一次读取和写入单个字符,这比head计数大时要慢得多。但是,对于count = 5来说并不明显。
迅速

2
那“ dd count = 1 bs = 5”呢?那将使头部一次读取五个字节。尽管如此,头脑可能还是一个更清晰的解决方案。
本·康比

1
谢谢-我实际上是在寻找一种“剪切”二进制文件的方法,而且dd看来可以解决问题。
sdaau,2010年

这是在busybox上的救命稻草,但没有head -c实施有效的dd bs=5 count=1方法
杰伊·帕罗林

11

名称

头-输出文件的第一部分

概要

[ 选项 ] ... [ 文件 ] ...

描述

将每个FILE的前10行打印到标准输出。如果有多个FILE,则在每个文件之前加上一个标头,以提供文件名。没有FILE或FILE为-时,读取标准输入。

长选项的强制性参数对于短选项也是必需的。
-c,-- bytes = [-] N 打印每个文件的前N个字节;以“-”开头,打印每个文件中除最后N个字节以外的所有字节


3

头或尾也可以做到:

头-c X

打印文件的前X个字节(如果是UTF-16文件,则不一定是字符)。除了最后的X个字节外,tail会执行相同的操作。

这(和剪切)是便携式的。


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行的5到8的字符

注意tail -1用于选择头部显示的最后一行。


2

您还可以将行grep出来,然后将其剪切,例如:

grep'text'文件名| 切-c 1-5


如果输入文件是无\ n的无休止的流,这将不起作用
Ajay Brahmakshatriya

2

我知道答案是对6年前提出的问题的答复...

但是我在找了几个小时后发现了类似的东西,然后才发现: cut -c确实做到了这一点,另外还可以指定一个偏移量。

cut -c 1-5将返回Hello,cut -c 7-11将返回world。无需任何其他命令


2
你的权利!。我只是想强调一个更通用的单个命令的可能性,该命令可以从文件的中间返回文本,而head -c只会读取起始字符,tail -c则读取最后一个字符。并且不使用grep :)。
bobbyus,2014年

2

即使几年前已经回答/接受了此答案,但目前接受的答案仅对每字符一个字节的编码(例如iso-8859-1)或可变字节字符集的单字节子集(例如拉丁字符)是正确的在UTF-8中)。即使使用多字节拼接,也仅适用于固定多字节编码,例如UTF-16。鉴于现在UTF-8是很好的道路上是一个通用的标准,并且在看的时候的语言这个名单母语的人数前30种语言的本地/二次使用的这个名单,它指出一个很重要简单的可变字节字符友好(不是基于字节的)技术,使用cut -ctr/ sed和字符类。

比较以下由于两个常见的以拉丁文为中心的关于字节与字符的问题(一个是headvs. cut,另一个是[a-z][A-Z]vs. [: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上工作正常,但是对我而言cuttr在GNU / Linux上和&仍然仍然以UTF-8破坏了希腊语):

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

另一个较新的答案已经提出“切割”,但这只是因为附带的问题,即它可以用于指定任意偏移量,而不是因为直接相关的字符vs.字节问题。

如果您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此处提到的方法进行了总结:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.