【问题标题】:Converting one file into another将一个文件转换为另一个文件
【发布时间】:2015-06-04 17:56:26
【问题描述】:

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

来源--------

    [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

服务器名可以取自源文件的文件名。

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

#!/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

【问题讨论】:

    标签: bash file loops awk sed


    【解决方案1】:

    我会使用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
    

    【讨论】:

    • 它不会为我产生任何输出。我将您的代码保存在 translate.awk 文件中并运行 awk -f translate.awk input.file。没有输出。
    • 嗯。我已经用问题中显示的数据对其进行了测试。您可以发布您的确切输入数据吗? (你使用的是 Linux,意思是gawk?)
    • 这是我的输入数据。
    • 输入刚刚粘贴在我的第一篇文章中的数据。
    • 另外,因为我有很多这样的文件,我想通过运行带有 2 个参数的命令来将它们一一转换。 awk -f translate.awk input.file output.file。输入文件名为 odbci_na01liwp01c334.ini 并具有要添加到输出行末尾的服务器的名称。
    【解决方案2】:

    也许可以用 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

    【讨论】:

    • “na01liwp01c334”的名称来源于源文件名——odbci_na01liwp01c334.ini
    • 在这种情况下,您可以执行my $hostname = $ARGV[0]; $hostname =~ s/odbci_(.*)\.ini/\1/; 和稍后的print "$line|$hostname\n"; 之类的操作。
    • 我真的很想避免使用 perl。看来我需要在服务器上安装它,我不能这样做。
    • Perl 默认是每个 GNU/Linux 发行版的一部分。但是,Config::IniFiles 包可能不会被安装。
    • 很少见到没有 Perl 的 UNIX 机器,但没关系。如果我是你,我会看看我可以使用哪些工具,以及其中一个是否包含 INI 解析器(例如 Python 的 configparser,尽管 Python 可能在没有的机器上太有希望了珀尔)。您可以看到脚本只有几行,没有什么特别之处,因此很容易翻译。除非我别无选择,否则我不会 尝试使用纯文本工具解析 INI 文件;当格式改变时,它一定会中断。​​
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多