Bash工具从文件获取第n行

|▌冷眼眸甩不掉的悲伤 提交于 2020-02-26 19:03:20

有没有一种“规范”的方式来做到这一点? 我一直在使用head -n | tail -1 head -n | tail -1可以达到目的,但是我一直在想是否有一个Bash工具专门从文件中提取一行(或一系列行)。

“规范”是指一个程序,其主要功能就是这样做。


#1楼

# print line number 52
sed '52!d' file

sed有用的单行脚本


#2楼

使用awk可以非常快:

awk 'NR == num_line' file

如果为true,则执行awk的默认行为: {print $0}


替代版本

如果您的文件碰巧很大,则最好在读取所需行后exit 。 这样可以节省CPU时间。

awk 'NR == num_line {print; exit}' file

如果要从bash变量中提供行号,可以使用:

awk 'NR == n' n=$num file
awk -v n=$num 'NR == n' file   # equivalent

#3楼

这个问题被标记为Bash,这是Bash(≥4)的处理方式:使用带有-s (跳过)和-n (计数)选项的mapfile

如果您需要获取文件file的第42行:

mapfile -s 41 -n 1 ary < file

此时,您将拥有一个数组ary ,该数组的字段包含file行(包括结尾的换行符),在此我们跳过了前41行( -s 41 ),并在读取了一行( -n 1之后)停止了-n 1 )。 这就是第42行。 要打印出来:

printf '%s' "${ary[0]}"

如果您需要一定范围的行,请说范围为42–666(含),并说您不想自己做数学,并在stdout上打印它们:

mapfile -s $((42-1)) -n $((666-42+1)) ary < file
printf '%s' "${ary[@]}"

如果您也需要处理这些行,则存储尾随的换行符并不是很方便。 在这种情况下,请使用-t选项(修剪):

mapfile -t -s $((42-1)) -n $((666-42+1)) ary < file
# do stuff
printf '%s\n' "${ary[@]}"

您可以使用一个函数为您执行此操作:

print_file_range() {
    # $1-$2 is the range of file $3 to be printed to stdout
    local ary
    mapfile -s $(($1-1)) -n $(($2-$1+1)) ary < "$3"
    printf '%s' "${ary[@]}"
}

没有外部命令,只有Bash内置函数!


#4楼

要使用带有变量作为行号的sed打印第n行:

a=4
sed -e $a'q:d' file

这里的-e标志用于将脚本添加到要执行的命令。


#5楼

对于大文件,最快的解决方案始终是tail | head,前提是两个距离:

  • 从文件的开头到起始行。 让我们称之为S
  • 从最后一行到文件末尾的距离。 成为E

众所周知。 然后,我们可以使用以下代码:

mycount="$E"; (( E > S )) && mycount="+$S"
howmany="$(( endline - startline + 1 ))"
tail -n "$mycount"| head -n "$howmany"

多少只是所需的行数。

https://unix.stackexchange.com/a/216614/79743中的更多详细信息

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!