使用 sed 使用存储在 shell 变量中的行号打印行

使用 sed 使用存储在 shell 变量中的行号打印行

我有一个选项卡文件,我正在从中提取包含行号的列,我需要从另一个文件中提取行。我得到了行号cut -f并将它们存储到一个变量中list。我尝试sed与以下内容一起使用:

$ list="2 5 7 10"
$ echo $list
2 5 7 10
$ sed -n "$list p" longText.txt 
sed: -e expression #1, char 3: unknown command: `5'
$ sed -n "${list}p" longText.txt 
sed: -e expression #1, char 3: unknown command: `5'

错误是什么?正确的语法是什么?

答案1

您的代码的问题是您尝试运行一个sed类似于

2 5 7 10p

这显然对 没有意义sed,所以它抱怨。

您的问题的一部分是使用单个字符串来保存许多不同的项目(行号)。最好使用数组来完成此操作。然后,每个数组元素(行号)需要在p其后插入一个 ,以使其成为一个单独的sed命令。

对于数字 2、5、7 和 10,您需要一个sed如下所示的脚本

2p; 5p; 7p; 10p;

或者

2p;5p;7p;10p;

或者

2p
5p
7p
10p

您可以从以下数组中轻松创建这样的脚本bash

lines=( 2 5 7 10 )
printf '%sp\n' "${lines[@]:-"q;"}" | sed -n -f /dev/stdin longText.txt

这用于从数字列表printf创建一个脚本,并将其提供给从标准输入读取它的脚本,并将其应用到您的文件。sedsed-f /dev/stdin

如果列表为空,则将printf发出一个sed不执行任何操作的表达式,然后终止sed


如果你需要要使用字符串中的数字,那么您可以将该字符串转换为有效的sed脚本并将其应用到您的文件,如下所示:

sed 's/[[:digit:]]\{1,\}/&p;/g' <<<"$list" | sed -n -f /dev/stdin longText.txt

给定 string 2 5 7 10,这将生成sed脚本2p; 5p; 7p; 10p;,然后以与上面类似的方式将其应用到您的文件。

空列表不会导致sed输出任何内容。

答案2

只需在命令之前添加一个 echosed即可查看哪里出错以及为什么出错。

使用编辑器的一种方法sed是:

# assuming default IFS
## based on Kusalananda's observations
set -f ;# disable globbing
list="2 5 7 10"
for i in $list;do
  echo "${i}p"
done | sed -nf - longText.txt

## or per Kusalanda method has a bug in it
## for empty list it generates wrong output
# printf '%sp\n' $list | sed -nf - lonxt.txt

相关内容