如何将文本文件拆分为特定格式的多个文件
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 脚本和适当的实用程序之间处理大文件的效率差异呈数量级增长。
我有这样的数据
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 脚本和适当的实用程序之间处理大文件的效率差异呈数量级增长。