我有一个扁平的档案记录,每33行长。我需要将这个文件格式化为模板中的规范。模板采用DOS格式,源文件采用NIX格式。模板具有特定的缩进和间距,必须遵守这些缩进和间距。我想了几个选择:
使用经典nix工具的
这些是我熟悉的顺序。下面是一个示例源记录( NIX格式):为了节省空间(通常是33行),我减少了换行符的数量:
JACKSON HOLE SANITARIUM AND REPTILE ZOO
45 GREASY HOLLER LN
JACKSON HOLE, AK 99999
Change Service Requested
BUBBA HOTEP
3 DELIVERANCE RD
MINNEAPOLIS, MN 99998
BUBBA HOTEP 09090909090909
You have a hold available for pickup as of 2012-01-04:
Title: Banjo for Fun and Profit
Author: Williams, Billy Dee
Price: $10 下面是模板( DOS格式--通常减少了66行):
<%BRANCH-NAME%>
<%BRANCH-ADDR%>
<%BRANCH-CTY%>
<%CUST-NAME%> <%BARCODE%>
You have a hold available for pickup as of <%DATE%>:
Title: <%TITLE%>
Author: <%AUTHOR%>
Price: <%PRICE%>
<%CUST-NAME%>
<%CUST-ADDR%>
<%CUST-CTY%>
end of file它实际上在每条记录的末尾写着“文件的结尾”。
有什么想法?我倾向于把事情复杂化。
UPDATE2
弄明白了。
我的答案如下。请随意提出改进建议。
发布于 2012-01-10 20:27:41
这就是我在这个项目中使用的。可以随意提出改进建议,或者提交更好的解决方案。
cp $FILE $WORKING # we won't mess with original
NUM_RECORDS=$( grep "^Price:" "$FILE" | wc -l ) # need to know how many records we have
# counting occurences of end of record r
TMP=record.txt # holds single record, used as temp storage in loop below
# Sanity
# Make sure temp storage exists. If not create -- if so, clear it.
[ ! -f $TMP ] && touch $TMP || cat /dev/null >$TMP
# functions
function make_template () {
local _file="$1"
mapfile -t filecontent < "$_file"
_loc_name="${filecontent[0]}"
_loc_strt="${filecontent[1]}"
_loc_city="${filecontent[2]}"
_pat_name="${filecontent[14]}"
_pat_addr="${filecontent[15]}"
_pat_city="${filecontent[16]}"
_barcode=${filecontent[27]:(-14)} # pull barcode from end of string
_date=${filecontent[29]:(-11)} # pull date from end of string
# Test title length - truncate if necessary - 70 chars.
_title=$(grep -E "^Title:" $_file)
MAXLEN=70
[ "${#_title}" -gt "$MAXLEN" ] && _title="${filecontent[31]:0:70}" || :
_auth=$(grep -E "^Author:" $_file)
_price=$(grep -E "^Price:" $_file)
sed "
s@<%BRANCH-NAME%>@${_loc_name}@g
s@<%BRANCH-ADDR%>@${_loc_strt}@g
s@<%BRANCH-CTY%>@${_loc_city}@g
s@<%CUST-NAME%>@${_pat_name}@g
s@<%CUST-ADDR%>@${_pat_addr}@
s@<%CUST-CTY%>@${_pat_city}@
s@<%BARCODE%>@${_barcode}@g
s@<%DATE%>@${_date}@
s@<%TITLE%>@${_title}@
s@<%AUTHOR%>@${_auth}@
s@<%PRICE%>@${_price}@" "$TEMPLATE"
}
####################################
# MAIN
####################################
for((i=1;i<="$NUM_RECORDS";i++))
do
sed -n '1,/^Price:/{p;}' "$WORKING" >"$TMP" # copy first record with end of record
# and copy to temp storage.
sed -i '1,/^Price:/d' "$WORKING" # delete first record using EOR regex.
make_template "$TMP" # send temp file/record to template fu
done
# cleanup
exit 0发布于 2012-01-07 00:56:13
首先,这里有一个提示: Perl这里-文档(仅显示几个替换作为演示):
#!/usr/bin/perl
use strict;
use warnings;
my @lines = qw/branchname cust_name barcode bogus whatever/; # (<>);
my ($branchname, $cust_name, $barcode, undef, $whatever) = @lines;
print <<TEMPLATE;
$branchname
<%BRANCH-ADDR%>
<%BRANCH-CTY%>
$cust_name $barcode
You have a hold available for pickup as of <%DATE%>:
Title: <%TITLE%>
Author: <%AUTHOR%>
Price: <%PRICE%>
$cust_name
<%CUST-ADDR%>
<%CUST-CTY%>
end of file
TEMPLATE如果愿意,用从stdin读取的行替换虚拟输入数组。(使用循环读取n行,如果这样做更有效,则将其推送到数组中)。我只是展示了要点,根据需要添加了更多的变量,并通过为“capture”变量指定undef来跳过输入行(如图所示)。
现在,简单地将这些变量插入到文本中。
如果线尾让你感到悲伤,请考虑使用chomp例如:
my @lines = (<>); # just read em all...
my @cleaned = map { chomp } @lines;https://stackoverflow.com/questions/8764521
复制相似问题