0

我有一个 db export .txt 文件。位于双引号中的元素(“Test_data1”)。元素之间的分隔符是制表符 (\t)。大小超过 1Gb。

Example(this is 1 string):

"Test_data1"    "Test_data2"    "1s"    "452"   "Test
data643"    "
"   "4d"    "System"    "Institute"

问题:在第二列中查找并打印具有特定条件的字符串

awk -F\"'\t'\" '$2 ~ /Test_data2/ {print $0}' input.txt >> sorted/result.txt

但是如何从这个搜索中排除双引号(“”)内的换行符(\n)?

我不能使用 RS 参数,因为我们在 "" ("\n") 中有一个换行符

4

2 回答 2

0

这是一般 CSV 解析问题的一个特例。通用解决方案由 Lorance Stinson (google Stinson awk CSV parser) 提供,但恕我直言,处理此特定问题的最简单方法是将双引号内的换行符转换为其他字符,以每记录单行格式对文件执行任何操作,然后转换回来,例如:

$ cat file
"Test_data1"    "Test_data2"    "1s"    "452"   "Test
data643"    "
"   "4d"    "System"    "Institute"
"Test_data3"    "Test_data4"    "2s"    "563"   "Test
data754"    "
"   "5d"    "Non System"    "Association"

要转换为单行:

$ awk -v FS= '{for (i=1;i<=NF;i++) if ($i=="\"") inQ=!inQ; ORS=(inQ?"♥":"\n") }1' file
"Test_data1"    "Test_data2"    "1s"    "452"   "Test♥data643"    "♥"   "4d"    "System"    "Institute"
"Test_data3"    "Test_data4"    "2s"    "563"   "Test♥data754"    "♥"   "5d"    "Non System"    "Association"

转换回来很简单tr

$ awk -v FS= '{for (i=1;i<=NF;i++) if ($i=="\"") inQ=!inQ; ORS=(inQ?"♥":"\n") }1' file | tr '♥' '
\n'
"Test_data1"    "Test_data2"    "1s"    "452"   "Test
data643"    "
"   "4d"    "System"    "Institute"
"Test_data3"    "Test_data4"    "2s"    "563"   "Test
data754"    "
"   "5d"    "Non System"    "Association"

上面使用 control-C 作为引号内的换行符的替换,选择您喜欢的任何字符(或字符串,如果您想使用 awk 或 sed 而不是 tr 转换回换行符)。

只需在 awk 和 tr 之间插入命令即可对原始文件执行任何操作,例如反向排序:

$ awk -v FS= '{for (i=1;i<=NF;i++) if ($i=="\"") inQ=!inQ; ORS=(inQ?"♥":"\n") }1' file | sort -r | tr '♥' '\n'
"Test_data3"    "Test_data4"    "2s"    "563"   "Test
data754"    "
"   "5d"    "Non System"    "Association"
"Test_data1"    "Test_data2"    "1s"    "452"   "Test
data643"    "
"   "4d"    "System"    "Institute"
于 2013-08-06T22:31:13.230 回答
0

如果你有gawk可用,你可以试试这个:

gawk 'BEGIN {FS = "\"\t\""; RS = "[^\t]\"\n"}; 
      $2 ~ /Test_data2/ {print $0 RT};' input.txt

否则你可以试试这个:

文件 a.awk:

BEGIN {RS="\t"; FS="\n"; rest = "";}

{    
    s = rest $0; i = 1; success = 0;

    while (1) 
    {   
        if (i == 2 && $1 ~ "f2") success = 1;    

        if ((NF == 2 && $0 ~ "\"\n\"") || (getline) <= 0)  
        {   
            rest = $2; 
            break;
        }   

        s = s RS $1; 
        i++;
    }   

    if (success) print s;
}

跑: awk -f a.awk input.txt

祝你好运。

于 2013-08-06T15:48:03.927 回答