1

我有一个完整的文件,其中包含如下记录:

"Full name","URL-style name","key_1a","key_2a"
"Full name","URL-style name","key_1b","key_2b"
"Full name","URL-style name","key_1c","key_2c"
...

我有另一个文件,里面有这样的记录:

"URL-style name","key_1a","key_2a"
"URL-style name","key_1b","key_2b"
"URL-style name","key_1c","key_2c"
...

知道 ( "key_1","key_2") 是主键(唯一),我想在第二个文件中添加该"Full name"列。

你会怎么做?我正在寻找带有vim或 in的解决方案bash shell script

4

4 回答 4

3

让我们对您的示例数据进行修改:

文件 1

"Full nameA","URL-style name","key_1a","key_2a"
"Full nameB","URL-style name","key_1b","key_2b"
"Full nameC","URL-style name","key_1c","key_2c"

文件2

"URL-style name1","key_1a","key_2a"
"URL-style name2","key_1b","key_2b"
"URL-style name3","key_1c","key_2c"

加工

如评论中所述,该命令的一个限制join是它只能连接单个列,但问题有一个包含两列的复合键。当然,有一些方法可以解决这个问题:基本上,您将输入重新格式化,join以便复合列可识别为使用的分隔符下的单个列,并且您必须确保每个文件中的数据按顺序正确排序复合柱。不过,join可能是这样做的方法;只需要一些准备工作和后处理。此外,Bash v4 具有“进程替换”,这对这个命令非常有用。

  1. file1使用我们需要的数据生成一个可连接的文件。

    做这件事有很多种方法; 两者sed(有点不可思议)或awk可以使用:

    $ sed 's/\([^,]*\),[^,]*,\([^,]*\),\([^,]*\)/\2:\3,\1/' file1
    "key_1a":"key_2a","Full nameA"
    "key_1b":"key_2b","Full nameB"
    "key_1c":"key_2c","Full nameC"
    $ awk -F, '{ printf "%s:%s,%s\n", $3, $4, $1 }' file1
    "key_1a":"key_2a","Full nameA"
    "key_1b":"key_2b","Full nameB"
    "key_1c":"key_2c","Full nameC"
    $
    
  2. file2使用我们需要的数据生成可连接文件:

    $ sed 's/\([^,]*\),\([^,]*\),\([^,]*\)/\2:\3,\1/' file2
    "key_1a":"key_2a","URL-style name1"
    "key_1b":"key_2b","URL-style name2"
    "key_1c":"key_2c","URL-style name3"
    $ awk -F, '{ printf "%s:%s,%s\n", $2, $3, $1 }' file2
    "key_1a":"key_2a","URL-style name1"
    "key_1b":"key_2b","URL-style name2"
    "key_1c":"key_2c","URL-style name3"
    $ 
    
  3. 鉴于这种预处理,直接sort就足以让数据准备好join

    $ join -t, -o 2.2,0,1.2 \
    >      <(awk -F, '{ printf "%s:%s,%s\n", $3, $4, $1 }' file1 | sort) \
    >      <(awk -F, '{ printf "%s:%s,%s\n", $2, $3, $1 }' file2 | sort)
    "URL-style name1","key_1a":"key_2a","Full nameA"
    "URL-style name2","key_1b":"key_2b","Full nameB"
    "URL-style name3","key_1c":"key_2c","Full nameC"
    $ 
    
  4. 现在我们需要将冒号后处理成逗号:

    $ join -t, -o 2.2,0,1.2 \
    >      <(awk -F, '{ printf "%s:%s,%s\n", $3, $4, $1 }' file1 | sort) \
    >      <(awk -F, '{ printf "%s:%s,%s\n", $2, $3, $1 }' file2 | sort) |
    > sed 's/":"/","/'
    "URL-style name1","key_1a","key_2a","Full nameA"
    "URL-style name2","key_1b","key_2b","Full nameB"
    "URL-style name3","key_1c","key_2c","Full nameC"
    $ 
    

显然,您可以选择任何合适的字符而不是冒号;Control-A(0x01) 不太可能出现在您的 HTML 中。

这假定,如图所示,您的 CSV 数据在字符串中没有逗号。如果字符串中有逗号,那么生活会更加艰难;您需要一个合适的 CSV 解释器来处理数据。Perl 有Text::CSV并且还有csvfix.

于 2013-03-09T16:52:40.590 回答
1

awk

$ awk -F, 'NR==FNR{a[$3$4]=$1;next}($2$3 in a){print a[$2$3]","$0}' file1 file2
"Full name","URL-style name","key_1a","key_2a"
"Full name","URL-style name","key_1b","key_2b"
"Full name","URL-style name","key_1c","key_2c"
于 2013-03-09T16:57:07.560 回答
0

您正在搜索的命令是join.

请参阅man join详细信息。

如果您遇到错误,例如pfull.txt:6: is not sorted您可以使用sort命令对输入文件进行排序,或者--nocheck-order尝试使用该选项。

于 2013-03-09T15:34:57.970 回答
0

如果您不必相互匹配条目,因为两个文件中的数据顺序相同:

使用 Vim 视觉块模式。

在 Vim 中的两个窗口中打开这两个文件(:sp <filename>:vsp <filename>将对此有所帮助),使用 开始块选择所需的文本CTRLv,使用 复制y

使用 在窗口之间移动CTRLwh j k l,具体取决于您是否有垂直或水平拆分。

将光标放在要粘贴剪贴板数据的位置,按p

于 2013-03-09T18:20:04.277 回答