【问题标题】:Shell, reading lines with variables and quoted stringsShell,读取带有变量和引用字符串的行
【发布时间】:2017-10-25 11:21:30
【问题描述】:

我正在尝试从 ksh 中的文件中读取变量。
但有些是单个单词/数字,有些是引号中的字符串
示例。

Field1a "this is field 2" 3 "And field 4"  
Field1b "2" "field three" 444444

我想分配变量。
通过1。

a=Field1a  
b="this is field 2"  
c=3  
d="And field 4"

通过 2

a=Field1b   
b="2"  
c="field three"  
d=444444  

怎么做?
我尝试过的所有尝试都只在空间上拆分,或者只在 " 上拆分。
我需要两者的巧妙结合。

【问题讨论】:

    标签: perl awk sed grep ksh


    【解决方案1】:

    这取决于你运行的是什么 ksh 版本,所以 idk 但这里是如何在 bash 中做到这一点:

    while IFS=$'\n' read -r -d '' a b c d; do
        echo "a=$a"
        echo "b=$b"
        echo "c=$c"
        echo "d=$d"
        echo "----"
    done < <(awk -v FPAT='[^ ]+|"[^"]+"' '{for (i=1;i<=NF;i++) print $i; printf "\0"}' file)
    a=Field1a
    b="this is field 2"
    c=3
    d="And field 4"
    ----
    a=Field1b
    b="2"
    c="field three"
    d=444444
    ----
    

    现在阅读 bash 的手册页和您的 ksh 版本,了解如何做同样的事情(或只使用 bash)。以上使用 GNU awk 进行 FPAT。

    【讨论】:

      【解决方案2】:

      您可以使用 csv 包。 Perl、ruby、python 都有可靠的程序。

      这是一个 Python 演示:

      python -c '
      import sys
      import csv
      
      for line in csv.reader(sys.stdin, delimiter=" "):
         print "\n".join(line)' <<<$(echo 'Field1a "this is field 2" 3 "And field 4"
      Field1b "2" "field three" 444444')
      

      打印:

      Field1a
      this is field 2
      3
      And field 4
      Field1b
      2
      field three
      444444
      

      【讨论】:

        【解决方案3】:

        您标记了perl,所以这是一个 perl 解决方案 - 使用 Text::ParseWords

        #!/usr/bin/env perl
        use strict;
        use warnings;
        use Text::ParseWords;
        use Data::Dumper;
        
        while (my $line = <DATA> ) {
          chomp $line; 
          my @fields = quotewords ( ' ', 0, $line );
        
          print Dumper \@fields;
        }
        
        __DATA__
        Field1a "this is field 2" 3 "And field 4"
        Field1b "2" "field three" 444444
        

        给予

        $VAR1 = [
                  'Field1a',
                  'this is field 2',
                  '3',
                  'And field 4'
                ];
        $VAR1 = [
                  'Field1b',
                  '2',
                  'field three',
                  '444444'
                ];
        

        因为 perl 确实精辟:

        my @stuff = map { chomp; [quotewords ( ' ', 0, $_ )] } <>;
        print Dumper \@stuff;
        

        【讨论】:

          【解决方案4】:

          如何分割字段上的线?
          字段开始时没有引号,直到第一个空格(或行尾),

          字段以引号开始,直到下一个引号(后跟空格或行尾)。

          字段与[^"]*( |$)"[^"]*"( |$) 匹配。

          您可以使用sed 插入字段分隔符,例如\r(在 windows 文件的 dos2unix 之后)。

          while IFS=$'\r' read -r a b c d e; do
             echo "a=$a"
             echo "b=$b"
             echo "c=$c"
             echo "d=$d"
             if [ -n "$e" ]; then
                echo "input has more than 4 fields, ignoring $e"
             fi
          done < <( sed -r 's/([^"]*|"[^"]*")( |$)/\1\r/g' inputfile)
          

          【讨论】:

            猜你喜欢
            • 2016-07-29
            • 1970-01-01
            • 2015-10-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-09
            • 1970-01-01
            相关资源
            最近更新 更多