我有一个要拆分的文件。该文件将具有头部和尾部记录。文件的主体包含NFD和IV记录。IV记录是可选的。在NFD记录中,它将在某个地方包含英语、法语或法语。对于英语,我希望NFD和IV转到en.txt,否则转到fr.txt。
示例如下:
1. 000000000000000;HDR;1;...
2. 000000008651776;NFD;Individual;...;English;...
3. 000000008651776;IV;....
4. 000000008657876;NFD;Individual;...;English;...
5. 000000008751796;NFD;Individual;...;French;...
6. 000000008751796;IV;...
7. 999999999999999;TRL;...我希望1,2,3,4,7行都转到en.txt,1,5,6,7行转到fr.txt
有什么建议使用K-shell脚本吗?谢谢!
发布于 2018-10-31 19:28:12
对于此任务,您需要实现状态解析。我不认为ksh只是一个重要的解决方案。
awk解决方案,以防万一:
$ awk '
/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9];HDR/ { enfile=enfile $0 RS; frfile=frfile $0 RS; }
/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9];NFD.*;English/ { enflag=1; frflag=0; enfile=enfile $0 RS; }
/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9];NFD.*;French/ { enflag=0; frflag=1; frfile=frfile $0 RS; }
/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9];IV/ { if ( enflag==1 ) enfile=enfile $0 RS; if ( frflag==1 ) frfile=frfile $0 RS; }
/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9];TRL/ { enfile=enfile $0; frfile=frfile $0; }
END { print(enfile) > "en.txt"; print(frfile) > "fr.txt"; }
' en_fr.txt
$ cat en.txt
000000000000000;HDR;1;...
000000008651776;NFD;Individual;...;English;...
000000008651776;IV;....
000000008657876;NFD;Individual;...;English;...
999999999999999;TRL;...
$ cat fr.txt
000000000000000;HDR;1;...
000000008751796;NFD;Individual;...;French;...
000000008751796;IV;...
999999999999999;TRL;...注意:如果您在/^[0-9]{15}/上,我使用regexp style: UNIX并不是为了具有本机awk兼容性。
发布于 2018-11-05 06:25:48
我相信这会做你想要的。这是在Linux上用ksh编写的,但可以在大多数版本的Unix上与bash或其他操作系统一起使用。
#!/bin/ksh
rm -f english.out
rm -f french.out
output=both
while read linein
do
echo $linein | grep HDR >/dev/null && output=both
echo $linein | grep English >/dev/null && output=english
echo $linein | grep French >/dev/null && output=french
echo $linein | grep TRL >/dev/null && output=both
case $output in
both)
echo "$linein" >> english.out
echo "$linein" >> french.out
;;
english)
echo "$linein" >> english.out
;;
french)
echo "$linein" >> french.out
;;
esac
done < data.txt通过解释的方式:
output变量设置为both。data.txt文件,一次一行读取linein变量。( while...done循环将其输入从data.txt文件重定向。)>>意味着将输出追加到文件中。请注意$linein周围的引号。如果它们不在那里,您就不能保留输入中的空格。这对你来说似乎无关紧要。如果您只想在字段5中查找英语或法语,它将变得更加复杂(并且不适用于bash (或ksh的旧版本)):
#!/bin/ksh
rm -f english.out
rm -f french.out
output=unknown
while read linein
do
if [[ $linein == {15}(\d)\;HDR* || $linein == {15}(\d)\;TRL* ]]
then
output=both
else
if [[ $linein == {15}(\d)\;+([A-Z])\;+([^\;])\;+([^\;])\;+([^\;])\;* ]]
then
case ${.sh.match[5]} in
English)
output=english
;;
French)
output=french
;;
*)
echo "unknown language: ${.sh.match[5]}" >&2
output=both
;;
esac
fi
fi
case $output in
both)
echo "$linein" >> english.out
echo "$linein" >> french.out
;;
english)
echo "$linein" >> english.out
;;
french)
echo "$linein" >> french.out
;;
*)
echo "Unknown output: $output" >&2
;;
esac
done < data.txt${.sh.match[5]}在匹配字符串( paren ()中的片段)中包含#5子表达式。
使用awk拉出子表达式更简单,但这是一个纯ksh解决方案。
https://stackoverflow.com/questions/53068436
复制相似问题