Shell,读取带有变量和引用字符串的行

时间:2017-05-24 23:04:32

标签: perl awk sed grep ksh

我正在尝试从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  

怎么做?
我尝试过的所有尝试都只在空间上分开,或者只在“仅” 我需要两者的智能组合。

4 个答案:

答案 0 :(得分:0)

这取决于你运行的ksh版本如此idk但是heres如何在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 for FPAT。

答案 1 :(得分:0)

您可以使用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

答案 2 :(得分:0)

您标记了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;

答案 3 :(得分:0)

如何拆分字段上的线?
在第一个空格(或行尾)之前,字段从没有引号开始 或
字段以引号开头,直到下一个引号(后跟空格或行尾)。

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

您可以使用sed插入fieldseperators,例如\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)