【问题标题】:Split linux files based on condition根据条件拆分linux文件
【发布时间】:2018-03-03 05:20:57
【问题描述】:

我在linux 中有一个文件。文件内容如下。

Test_12
Test_abc
start_1
start_abcd
end_123
end_abcde_12

现在我想根据第一个 underscore 之后的匹配字符串将文件拆分为多个小文件

输出:

  • Test.txt:

    Test_12
    Test_abc
    
  • start.txt:

    start_1
    start_abcd  
    
  • end.txt:

    end_123
    end_abcde_12
    

我已经尝试过如下

while read -r line ; do
    echo "$line" >> "${line}.txt"  
done < split.txt

但我得到了每一行的文件。

我在这里做错了什么,如何获得我想要的输出?

【问题讨论】:

    标签: linux bash awk


    【解决方案1】:

    最好使用 awk:

    awk -F_ 'p && $1 != p{close(fn)} {p=$1; fn=p ".txt"; print>>fn} END{close(fn)}' split.txt
    

    当第一列中的值发生变化时,需要进行一些额外的处理来关闭文件,这样如果您的输入文件很大,我们就不会打开太多的文件。

    【讨论】:

    • 我可能误读了它,但我认为 1 美元永远不可能等于 fn。您不需要在 END 中关闭(),顺便说一句 - 默认情况下,awk 会这样做。
    【解决方案2】:

    您需要修剪每行的下划线和尾随文本。 %%_* 这样做:

    while read -r line ; do
        echo "$line" >> "${line%%_*}.txt"  
    done < split.txt
    

    解释:

    • %: 修剪尾随文本
    • %%: 找到最长的匹配项
    • _*: 下划线和后面的所有内容

    【讨论】:

    • 这将删除每行的所有前导和尾随空格,这可能不是 OP 所期望的(尤其是尾随空格)。始终在读取时设置IFS=,除非您有特定的目标需要保留它。它也将比等效的 awk 脚本慢一个数量级,并且会根据您的路径中的 echo 版本产生不同的输出。见why-is-using-a-shell-loop-to-process-text-considered-bad-practice
    【解决方案3】:

    阅读why-is-using-a-shell-loop-to-process-text-considered-bad-practice,然后使用 awk。

    使用 GNU awk,您只需要:

    awk -F'_' '{print > ($1".txt")}' file
    

    否则对于其他 awk,如果您的输入文件按问题中所示的第一个字段分组,那么您只需要:

    awk -F'_' '{f=$1".txt"; print > f} f!=p{close(p); p=f}' file
    

    如果不是,那么它的效率会稍低,因为您可能需要重新打开以前关闭的文件(因此使用 &gt;&gt; 而不是 &gt;):

    awk -F'_' '{f=$1".txt"; print >> f} f!=p{close(p); p=f}' file
    

    【讨论】:

      【解决方案4】:

      你能试试这个吗:

      while read line; do
          content=`echo $line|awk 'BEGIN{FS="_"}{print $1}'`
          for f in *; do
              filename=`echo $f|awk 'BEGIN{FS="."}{print $1}'`
              if [ "$content" == "$filename" ]; then
                  echo $line>>$f
                  break
              else
                  echo $line>>$content.txt
                  break
              fi
          done
      done< file.txt
      

      输出:

      bash-4.4$ ls -lrt
      total 12
      -rw-r--r-- 1 21726 21726 978 Sep 22 04:54 README.txt
      -rw-r--r-- 1 21726 21726  49 Sep 22 04:56 file.txt
      -rwxr-xr-x 1 21726 21726 252 Sep 22 05:06 script.sh
      bash-4.4$ cat file.txt
      Test_12
      Test_abc
      Start_1
      Start_abc
      end_1
      end_abc
      bash-4.4$ ./script.sh
      bash-4.4$ ls -lrt
      total 24
      -rw-r--r-- 1 21726 21726 978 Sep 22 04:54 README.txt
      -rw-r--r-- 1 21726 21726  49 Sep 22 04:56 file.txt
      -rwxr-xr-x 1 21726 21726 252 Sep 22 05:06 script.sh
      -rw-r--r-- 1 21726 21726  17 Sep 22 05:06 Test.txt
      -rw-r--r-- 1 21726 21726  18 Sep 22 05:06 Start.txt
      -rw-r--r-- 1 21726 21726  14 Sep 22 05:06 end.txt
      bash-4.4$ cat Start.txt
      Start_1
      Start_abc
      bash-4.4$ cat Test.txt
      Test_12
      Test_abc
      bash-4.4$ cat end.txt
      end_1
      end_abc
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-17
        • 2010-10-31
        • 1970-01-01
        • 1970-01-01
        • 2018-09-13
        • 2012-01-22
        相关资源
        最近更新 更多