Jos*_*sja 6 command-line sed text-processing
我有一个 shell 脚本,它本质上是一个带有一些检查的 sed 脚本。该脚本的目标是转换文件的头文件。
&FCI
NORB=280,
NELEC=78,
MS2=0,
UHF=.FALSE.,
ORBSYM=1,1,1,1,1,1,1,1,<...>
&END
1.48971678130072078261E+01 1 1 1 1
-1.91501428271686324756E+00 1 1 2 1
4.38796949990802698238E+00 1 1 2 2
Run Code Online (Sandbox Code Playgroud)
到
&FCI NORB=280, NELEC=78, MS2=0, UHF=.FALSE.,
ORBSYM=1,1,1,1,1,1,1,1,<...>
ISYM=1,
/
1.48971678130072078261E+01 1 1 1 1
-1.91501428271686324756E+00 1 1 2 1
4.38796949990802698238E+00 1 1 2 2
Run Code Online (Sandbox Code Playgroud)
这是脚本:
#!/bin/bash
# $1 : FCIDUMP file to convert from "new format" to "old format"
if [ ${#} -ne 1 ]
then
echo "Syntaxis: fcidump_new2old FCIDUMPFILE" 1>$2
exit 1
fi
if egrep '&FCI ([a-zA-Z2 ]*=[0-9 ]*,){2,}' ${1} > /dev/null
then
echo "The provided file is already in old FCIDUMP format." 1>&2
exit 2
fi
sed '
1,20 {
:a; N; $!ba
s/\(=[^,]*,\)\n/\1 /g
s/\(&FCI\)\n/\1 /
s/ORBSYM/\n&/g
s/&END/ISYM=1,\n\//
}' -i "${1}"
exit 0
Run Code Online (Sandbox Code Playgroud)
这个脚本适用于“小”文件,但现在我遇到了一个大约 9 GB 的文件,脚本崩溃并显示“超级清晰的错误消息”:
script.sh: line 24: 406089 Killed sed '
1,20 {
:a; N; $!ba
s/\(=[^,]*,\)\n/\1 /g
s/\(&FCI\)\n/\1 /
s/ORBSYM/\n&/g
s/&END/ISYM=1,\n\//
}' -i "${1}"
Run Code Online (Sandbox Code Playgroud)
我怎样才能让这个 sed 脚本真正只查看标题并能够处理这么大的文件?顺便说一句,丑陋的硬编码“20”在那里,因为我不知道更好。
额外信息:
在尝试了一些事情后,我看到生成了奇怪的文件:sedexG4Lg、sedQ5olGZ、sedXVma1Y、sed21enyi、sednzenBn、sedqCeeey sedzIWMUi。除了 sednzenBn 之外,所有内容都是空的,它只是输入文件的一半而已。
丢弃 -i 标志并将输出重定向到另一个文件会产生一个空文件。
head
和tail
创建头文件和数据文件。您可以使用cat
来连接修改后的头文件和数据文件。
我用你的标头和一个包含 1080000000 行编号的文件(大小 19 Gib)进行了测试,总共 1080000007 行,并且它有效,输出文件(包含 1080000004 行)在我的旧 hp xw8400 工作站中用了 5 分钟写入(包括键入命令启动 shell 脚本)。
$ ls -lh --time-style=full-iso huge*
-rw-r--r-- 1 sudodus sudodus 19G 2018-12-15 19:50:45.278328120 +0100 huge.in
-rw-r--r-- 1 sudodus sudodus 19G 2018-12-15 19:55:46.808798456 +0100 huge.out
Run Code Online (Sandbox Code Playgroud)大写操作发生在 SSD 上的系统分区和 HDD 上的数据分区之间。
您需要在文件系统中有足够的可用空间/tmp
来容纳巨大的临时“数据”文件,根据您最初的问题,该空间超过 9 GB。
$ LANG=C df -h /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 106G 32G 69G 32% /
Run Code Online (Sandbox Code Playgroud)
这似乎是一种尴尬的做法,但它适用于大文件,而且不会导致工具崩溃。也许您必须将临时“数据”文件存储在其他地方,例如外部驱动器中(但它可能会更慢)。
#!/bin/bash
# $1 : FCIDUMP file to convert from "new format" to "old format"
if [ $# -ne 2 ]
then
echo "Syntaxis: $0 fcidumpfile oldstylefile " 1>&2
echo "Example: $0 file.in file.out" 1>&2
exit 1
fi
if [ "$1" == "$2" ]
then
echo "The names of the input file and output file must differ"
exit 2
exit
fi
endheader="$(grep -m 1 -n '&END' "$1" | cut -d: -f1)"
if [ "$endheader" == "" ]
then
echo "Bad input file: the end marker of the header was not found"
exit 3
fi
#echo "endheader=$endheader"
< "$1" head -n "$endheader" > /tmp/header
#cat /tmp/header
if egrep '&FCI ([a-zA-Z2 ]*=[0-9 ]*,){2,}' /tmp/header > /dev/null
then
echo "The provided file is already in old FCIDUMP format." 1>&2
exit 4
fi
# run sed inline on /tmp/header
sed '
{
:a; N; $!ba
s/\(=[^,]*,\)\n/\1 /g
s/\(&FCI\)\n/\1 /
s/ORBSYM/\n&/g
s/&END/ISYM=1,\n\//
}' -i /tmp/header
if [ $? -ne 0 ]
then
echo "Failed to convert the header format in /tmp/header"
exit 5
fi
< "$1" tail -n +$(($endheader+1)) > /tmp/tailer
if [ $? -ne 0 ]
then
echo "Failed to create the 'data' file /tmp/tailer"
exit 6
fi
#echo "---"
#cat /tmp/tailer
#echo "---"
cat /tmp/header /tmp/tailer > "$2"
exit 0
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
545 次 |
最近记录: |