将一个文件转换为另一个文件

时间:2015-03-31 11:45:19

标签: bash file loops awk sed

您好我正在尝试转换此源文件:

来源--------

    [ODBC Data Sources]
C334_DEV_MD=Micro ODBC Driver for SQL Server Wire Protocol
C334_PRD_ST=Micro ODBC Driver for SQL Server Wire Protocol

[ODBC]
Trace=0
TraceFile=odbctrace.out
TraceDll=/home/mstr/Micro/install/lib32/MYtrcXX.so
InstallDir=/home/mstr/Micro/install
IANAAppCodePage=106
UseCursorLib=0

[C334_DEV_MD]
HostName=C334WM01NA02
PortNumber=1433
Database=C334_DEV_MD
DoubleToStringPrecision=17

[C334_PRD_ST]
HostName=C334WM01NA02
PortNumber=1433
Database=C334_PRD_ST
DoubleToStringPrecision=17

源----------

使用脚本进入此文件。

目的地--------

C334_DEV_MD=Driver description|HostName=C334WM01NA02;PortNumber=1433;Database=C334_DEV_MD;DoubleToStringPrecision=17|na01liwp01c334
C334_PRD_ST=Driver description|HostName=C334WM01NA02;PortNumber=1433;Database=C334_PRD_ST;DoubleToStringPrecision=17|na01liwp01c334

目的地---------

ODBC条目在这里并不重要。

这是输出应遵循的模式。

DSN_entry=Driver Description|Parameter1=value;Parameter2=value;Parameter3=value|Server_Name

可以从源文件的文件名中获取Servername。

这是我到目前为止所做的,但我被卡住了。

#!/bin/bash
flag=0
sourcefile=$1
destfile=$2
sed -n '2,/^$/p' $sourcefile | awk -F"=" '{print$1}' | sed '$d' | \
while read line; do
        #echo $line
        grep -E ''"^${line}"'|'"^\[${line}"'' $sourcefile
done

2 个答案:

答案 0 :(得分:0)

我会使用awk

# Record definitions
BEGIN {
  FS="\n"; OFS="|"; RS="\n\n"; ORS="\n"
}

# Parse data source descriptions
$1 ~ /ODBC Data Source/ {
    for(i=2; i<= NF; i++) {
        split($i, a, "=")
        n[a[1]]=a[2]
    }
}

# Output the result record. Replace the datasource id
# by the description
$1 ~ /DSN_entry/{
    gsub(/\[|\]/,"",$1)
    print n[$1],$2,$3,$4
}

将上述脚本保存到文件translate.awk中,并按以下方式调用:

awk -f translate.awk input.file

答案 1 :(得分:0)

有可能用awk一起破解一些东西,但我认为更合适的替代方法是使用正确的INI文件解析器。例如,使用Perl和Config::IniFiles

#!/usr/bin/perl

use Config::IniFiles;

# We expect the INI file to be given as first parameter.
scalar(@ARGV) > 0 || die "Missing parameter";

my $hostname = $ARGV[0];
$hostname =~ s/odbci_(.*)\.ini/\1/;

# You may want to also pass -nocase => 1 here, for case-insensitive matching
my $cfg = Config::IniFiles->new( -file => $ARGV[0]);

my @sources = $cfg->Parameters('ODBC Data Sources');

foreach $source (@sources) {
    my $line = "$source=" . $cfg->val('ODBC Data Sources', $_);
    my @params = $cfg->Parameters($source);

    my $sep = "|";
    foreach (@params) {
        $line .= "$sep$_=" . $cfg->val($source, $_);
        $sep = ";";
    }

    print "$line|$hostname\n";
}

Python 2中的相同内容:

#!/usr/bin/python

import ConfigParser
import re
import sys

if len(sys.argv) < 2:
    print "Need input file parameter"
    sys.exit(1)

inifile = sys.argv[1]
hostname = re.search('odbci_(.*)\.ini', inifile, re.IGNORECASE).group(1)

cfg = ConfigParser.SafeConfigParser()
cfg.optionxform = lambda option: option
cfg.read(inifile)

for source in cfg.options('ODBC Data Sources'):
    line = source + '=' + cfg.get('ODBC Data Sources', source)
    sep = '|'
    for param in cfg.options(source):
        line = line + sep + param + '=' + cfg.get(source, param)
        sep = ';'

    print line + '|' + hostname

...在Python 3中:

#!/usr/bin/python3

import configparser
import re
import sys

if len(sys.argv) < 2:
    print("Need input file parameter")
    sys.exit(1)

inifile = sys.argv[1]
hostname = re.search('odbci_(.*)\.ini', inifile, re.IGNORECASE).group(1)

cfg = configparser.SafeConfigParser()
cfg.optionxform = lambda option: option
cfg.read(inifile)

for source in cfg['ODBC Data Sources']:
    line = source + '=' + cfg['ODBC Data Sources'][source]
    sep = '|'
    for param in cfg[source]:
        line = line + sep + param + '=' + cfg[source][param]
        sep = ';'

    print(line + '|' + hostname)

所有这些都希望被称为scriptname odbci_hostname.ini