以特定顺序从文件中选择某些行的简便方法

Kar*_*lek 5 linux bash

我有一个文本文件,有很多行.我也有一定数量的线要打印出来,按一定的顺序排列.比方说,例如,"5,3,10,6".按此顺序.

这样做有一些简单和"规范"的方式吗?(使用"标准"Linux工具和bash)

当我尝试这个问题的答案时

Bash工具从文件中获取第n行

它总是按照文件中的顺序打印行.

gni*_*urf 2

如果您的文件不是太大,一种相当有效的方法是将其全部读取到内存中的数组中,每个字段一行,使用mapfile(这是一个 Bash \xe2\x89\xa54 内置函数):

\n\n
mapfile -t array < file.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后您可以按任何顺序回显您想要的所有行,例如,

\n\n
printf \'%s\\n\' "${array[4]}" "${array[2]}" "${array[9]}" "${array[5]}"\n
Run Code Online (Sandbox Code Playgroud)\n\n

打印第 5、3、10、6 行。现在您会觉得数组字段以 a 开头有点尴尬,0因此您必须偏移数字。-O通过选择以下选项可以轻松解决此问题mapfile

\n\n
mapfile -t -O 1 array < file.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将从索引 1开始分配array,以便您可以将第 5、3、10 和 6 行打印为:

\n\n
printf \'%s\\n\' "${array[5]}" "${array[3]}" "${array[10]}" "${array[6]}"\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后,您想为此创建一个包装函数:

\n\n
printlines() {\n    local i\n    for i; do printf \'%s\\n\' "${array[i]}"; done\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这样你就可以声明:

\n\n
printlines 5 3 10 6\n
Run Code Online (Sandbox Code Playgroud)\n\n

而且都是纯 Bash,没有外部工具!

\n\n
\n\n

正如 @glennjackmann 在评论中建议的那样,您可以使辅助函数也负责读取文件(作为参数传递):

\n\n
printlinesof() {\n    # $1 is filename\n    # $2,... are the lines to print\n    local i array\n    mapfile -t -O 1 array < "$1" || return 1\n    shift\n    for i; do printf \'%s\\n\' "${array[i]}"; done\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后您可以将其用作:

\n\n
printlinesof file.txt 5 3 10 6\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您还想处理标准输入:

\n\n
printlinesof() {\n    # $1 is filename or - for stdin\n    # $2,... are the lines to print\n    local i array file=$1\n    [[ $file = - ]] && file=/dev/stdin\n    mapfile -t -O 1 array < "$file" || return 1\n    shift\n    for i; do printf \'%s\\n\' "${array[i]}"; done\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

以便

\n\n
printf \'%s\\n\' {a..z} | printlinesof - 5 3 10 6\n
Run Code Online (Sandbox Code Playgroud)\n\n

也会起作用。

\n