如何将文本文件拆分为特定格式的多个文件

how to split a text file in several files with certain format

我有这样的数据

POW076956-1 CC1=CC=C(C=C1)C(=O)N1N=C(CC1C1=CC=CO1)C1=CC=C(NS(C)(=O)=O)C=C1
POW000136-2 CCCCOC1=CC=C(OCCCC)C2=C1NC1(N2)C(=O)NC2=CC=C(C=C12)[N+]([O-])=O
POW192689-1 CC(C)(C)C1=CC=C(C=C1)C1N(CCN2C=CC=C12)S(=O)(=O)C1=CC=C2C=CC=CC2=C1
POW005144-1 CC1=CC=C2N=C(OC2=C1)C1=CC=C(NC(=O)C2=CC=C(I)C=C2)C=C1
POW146687-1 O=S(=O)(C1=CC=CC=C1)C1=CC=C(COC2=CC=CC3=CC=CN=C23)C=C1
POW008940-2 OC(CNC1=CC=CC=C1)CN1C2=CC=C(I)C=C2C2=C1C=CC(I)=C2

我想在每一行中取出第二部分并将其放入一个与第一部分同名的文件中并将其格式化为 .txt

比如拿这个

CC1=CC=C(C=C1)C(=O)N1N=C(CC1C1=CC=CO1)C1=CC=C(NS(C)(=O)=O)C=C1

放入文件

使用名称 POW076956-1.txt

保存文件

像下面这样的东西应该可以工作:

#!/usr/bin/env bash

while read -r file data; do
    echo "$data" > "$file.txt"
done < 'input'

使用sed

$ sed 's/\([^ ]*\) \(.*\)/echo "" > .txt/e' input_file
$ cat POW000136-2.txt
CCCCOC1=CC=C(OCCCC)C2=C1NC1(N2)C(=O)NC2=CC=C(C=C12)[N+]([O-])=O
awk '{print  > ".txt"}' input_file

find . -name "*.txt"
./POW000136-2.txt
./POW005144-1.txt
./POW008940-2.txt
./POW076956-1.txt
./POW146687-1.txt
./POW192689-1.txt

cat ./POW000136-2.txt
CCCCOC1=CC=C(OCCCC)C2=C1NC1(N2)C(=O)NC2=CC=C(C=C12)[N+]([O-])=O

就我个人而言,我会使用 awk,但您已将问题标记为 [bash],因此 bash 解决方案一次读取整行,然后使用 parameter-expansion 删除子字符串 将行分隔成 two-parts 在 space 很容易完成。

假设您提供要读取的文件名作为程序的第一个参数,可以通过以下方式完成:

## loop reading each line
while read -r line || [ -n "$line" ]; do
  ## separate with parameter expansion & redirect to file
  printf "%s\n" "${line#* }" > "${line%% *}"
done < ""

trim从左右(前后)展开的参数总结如下:

${var#pattern}      # Strip shortest match of pattern from front of $var
${var##pattern}     # Strip longest match of pattern from front of $var
${var%pattern}      # Strip shortest match of pattern from back of $var
${var%%pattern}     # Strip longest match of pattern from back of $var

您需要对提供给程序的文件名参数执行多项验证。首先,您要检查至少提供了一个参数,其次,您要验证该参数是一个有效的文件名并且该文件是 non-empty。总而言之,您可以这样做:

#!/bin/bash

[ -z "" ] && {  ## validate 1 argument given for filename
  printif "error: filename required.\nusage: %s file\n" "./${0##*/}" >&2
  exit 1
}

[ -s "" ] || {  ## validate file exists and is non-empty
  printf "error: file doesn't exist or is empty.\n" >&2
  exit 1
}

## loop reading each line
while read -r line || [ -n "$line" ]; do
  ## separate with parameter expansion & redirect to file
  printf "%s\n" "${line#* }" > "${line%% *}"
done < ""

例子Use/Output

在名为 file 的文件中输入示例,在 splitfile.sh 中输入脚本,您可以:

$ bash splitfile.sh file

创建的结果文件:

$ ls -al POW*
-rw-r--r-- 1 david david 64 May  4 19:53 POW000136-2
-rw-r--r-- 1 david david 54 May  4 19:53 POW005144-1
-rw-r--r-- 1 david david 50 May  4 19:53 POW008940-2
-rw-r--r-- 1 david david 63 May  4 19:53 POW076956-1
-rw-r--r-- 1 david david 55 May  4 19:53 POW146687-1
-rw-r--r-- 1 david david 67 May  4 19:53 POW192689-1

列出的第一个文件的示例内容:

$ cat POW000136-2
CCCCOC1=CC=C(OCCCC)C2=C1NC1(N2)C(=O)NC2=CC=C(C=C12)[N+]([O-])=O

注意: 对于几千行或 ten-thousand 左右的输入文件,bash 脚本没问题。对于一百万行或更多行,请使用 awk(或 sed)。随着文件大小越来越大,shell 脚本和适当的实用程序之间处理大文件的效率差异呈数量级增长。