我有一个文件,如下所示:
###PSTERS###
LINE1
LINE2
###PSTADS###
LINE3
LINE4
###PSTEEE###
LINE5
LINE6
我需要生成 3 个文件(文件名是我们正在搜索的模式):
PSTERS.txt:
LINE1
LINE2
PSTADS.txt:
LINE3
LINE4
PSTEEE.txt:
LINE5
LINE6
我怎样才能做到这一点?我尝试了下面的脚本,但由于 awk 语法错误而失败:
#!/bin/bash
#This script will take 2 parameters as input.
# 1. Source File Path
# 2. Source File name as input
SOURCE_PATH=$1
SOURCE_FILE=$2
#Get the list of patterns we need to check from the Main source file
cd $SOURCE_PATH
pattern_list=`grep -e '^\#' $SOURCE_FILE | cut -d'#' -f4`
echo ${pattern_list}
#Split the Source File for each pattern in the variable pattern_list
for pattern in ${pattern_list}
do
cd $SOURCE_PATH
awk '/\#\#\#'$pattern'/{x='$pattern';next}{print > x;}' $SOURCE_FILE
done
答案1
你正在采取一种非常复杂的方法。不需要 shell 脚本,这是awk
一行代码:
awk '{if(gsub(/#+/,"")){name=$0;}else{print > name".txt"}}' file
这gsub
就是“全球替换”。因此,上面的意思是“如果一行有任何#
,则删除它们(替换为空),并将变量“name”设置为该行的内容”。由于该行现在将是删除后剩下的所有内容#
,name
因此将成为模式。然后,如果该行与 a 不匹配#
(如果替换失败),则将该行打印到名称为name
和的当前值的文件中.txt
。
如果您仍然需要包装脚本,只需使用:
#!/bin/bash -
#This script will take 1 parameter as input: the target file path
targetFile="$1"
targetDir=$(dirname -- "$targetFile")
targetFile=$(basename -- "$targetFile")
cd -P -- "$targetDir" || exit
awk '{if(gsub(/#+/,"")){name=$0;}else{print > name".txt"}}' < "$targetFile"
答案2
我们可以使用relative addressing
编辑ed
器来实现这一点。
#
任务涉及在第一遍中提取输入文件中所有行的行号。然后我们生成一系列ed
命令来完成工作。右侧显示由sed
抄写员塑造的图案空间的内容
sed -e '$s/.*/$/;$q;/^#/!d;=' inputfile |
sed -e '
N;N;h; # p.s.: 1\n###PSTERS###\n4$
s/^[1-9][0-9]*/&+/; /\$$/!s/$/-/; # p.s.: 1+\n###PSTERS###\n4-$
s/\n\(.*\)\n\(.*\)/,\2w \1.txt/; # p.s.: 1+,4-w ###PSTERS###.txt$
s/#//gp;g; # p.s.: 1+,4-w PSTERS.txt
s/.*\n/\n/; $!D; s/.*/q/
' |
ed -s - inputfile