【问题标题】:extracting specified line numbers from file using shell script使用shell脚本从文件中提取指定的行号
【发布时间】:2012-08-02 14:06:02
【问题描述】:

我有一个包含地址列表的文件,它看起来像这样 (ADDRESS_FILE)

0xf012134  
0xf932193  
.  
.  
0fx12923a

我有另一个文件,其中包含如下所示的数字列表 (NUMBERS_FILE)

20  
40  
.  
.  
12

我想从 ADDRESS_FILE 中删除前 20 行并将其放入一个新文件中
然后从 ADDRESS_FILE 中删除接下来的 40 行,依此类推...

我知道下面给出的一系列 sed 命令可以完成这项工作

sed -n 1,20p ADDRESSS_FILE > temp_file_1
sed -n 20,60p ADDRESSS_FILE > temp_file_2
.  
.
sed -n somenumber,endofilep.  ADDRESS_FILE > temp_file_n

但我想使用 shell 脚本自动执行此操作,这将更改每次 sed 执行时要剪切的行数。

如何做到这一点???

另外,在一般情况下,哪些是 linux 中的文本处理命令在这种情况下非常有用?

【问题讨论】:

  • Wrt 文本处理命令,很多都可以直接由你的 shell 完成,所以要熟悉它。如果您使用的是基于 GNU 的系统,我建议您阅读 coreutils.infosed.info。对于更复杂的任务awkperl 很好。

标签: linux shell


【解决方案1】:

假设您的行号位于名为lines 的文件中,已排序等,请尝试:

#!/bin/sh

j=0
count=1
while read -r i; do
  sed -n $j,$i > filename.$count  # etc... details of sed/redirection elided
  j=$i
  count=$(($count+1))
done < lines

注意。上面没有假设每次迭代要分割的行数一致。

由于您还要求提供通用实用程序,请尝试split。但是,这会在一致的行数上拆分,并且在这里可能用途有限。

【讨论】:

  • 您不应该使用 for 循环来读取文件中的行。它恰好在这种情况下起作用,只是因为每行有一个单词。这是总体上不好的做法。使用while read -r line; do ...; done &lt; file
  • 它在这种情况下有效,因为他是这样指定的。查看问题。
  • 这不是以错误方式做事的理由。 Don't Read Lines With For.
  • 我不同意有更好的方法,值得指出。然而,对完整的解决方案(包括详细的替代选项)投反对票似乎特别小气
  • 这行得通,但我不明白它是如何工作的 :) 不要只给饥饿的人鱼,教他钓鱼 :) ......一个人需要学习的工具怎么样文本操作?请回答,这样我也可以像从你们那里得到的一样帮助别人。
【解决方案2】:

这是直接从NUMBERS_FILE 读取的替代方案:

n=0; i=1
while read; do 
  sed -n ${i},+$(( REPLY - 1 ))p ADDRESS_FILE > temp_file_$(( n++ ))
  (( i += REPLY ))
done < NUMBERS_FILE

【讨论】:

    【解决方案3】:
    size=$(wc -l ADDRESSS_FILE)
    i=1
    n=1
    while [ $n -lt $size ]
    do
      sed -n $n,$((n+19))p ADDRESSS_FILE > temp_file_$i
      i=$((i+1))
      n=$((n+20))
    done
    

    或者只是

    split -l20 ADDRESSS_FILE temp_file_
    

    (感谢 Brian Agnew 的想法)。

    【讨论】:

    • 我认为 $ 不能在 sed 中使用。我出错了。而是使用这个a=2 b=4 sed '/$a/,/$b/p' input_file &gt; new_file
    • @Deepthought:抱歉,在我的示例中,很多情况下它必须是 $(()) 而不是 $();我修好了。 $n$((n+20)) 当然可以在 sed 中使用,因为实际上在 sed 中没有,在 shell 中;并扩展它
    【解决方案4】:

    使用单个 sed 调用的丑陋解决方案可能会变得不那么可怕。

    这会生成一个小 sed 脚本来拆分文件

    #!/bin/bash
    sum=0
    count=0
    sed -n -f <(while read -r n ; do
        echo $((sum+1),$((sum += n)) "w temp_file_$((count++))" ;
    done < NUMBERS_FILE) ADDRESS_FILE
    

    【讨论】:

    • 这行得通,但我不明白它是如何工作的 :) 不要只给饥饿的人鱼,教他钓鱼 :) ......一个人需要学习的工具怎么样文本操作?请回答,这样我也可以像从你们那里得到的一样帮助别人
    • 抱歉,它的作用如下:它遍历NUMBERS_FILE,为每组行生成一个sed 写入命令,例如1,20 w temp_file_021,60 w temp_file_1 等等。 sed依次处理每个地址范围,将输出写入相关文件
    猜你喜欢
    • 2011-09-08
    • 2015-08-16
    • 2019-10-15
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 2022-11-14
    相关资源
    最近更新 更多