我有一个要分割的文件。该文件将具有标题和尾部记录。文件的正文包含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脚本的建议吗?
谢谢!
答案 0 :(得分:0)
对于此任务,您需要实现状态解析。我不认为ksh仅是至关重要的解决方案。
万一需要的解决方案:
$ 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;...
注意:如果您在UNIX上,我没有使用正则表达式样式:/^[0-9]{15}/
是为了具有本机awk兼容性。
答案 1 :(得分:0)
我相信这会做您想要的。这是在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
变量设置为两者。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]}
在匹配字符串(括号()
中的部分)中包含#5子表达式。
使用awk
提取子表达式比较简单,但这是纯粹的ksh
解决方案。