Linux join实用程序抱怨输入文件未被排序

Raz*_*van 6 linux sorting bash text-processing join

我有两个文件:

file1的格式为:

field1;field2;field3;field4
Run Code Online (Sandbox Code Playgroud)

(file1最初未排序)

file2的格式为:

field1
Run Code Online (Sandbox Code Playgroud)

(file2已排序)

我运行以下两个命令:

sort -t\; -k1 file1 -o file1 # to sort file 1
join -t\; -1 1 -2 1 -o 1.1 1.2 1.3 1.4 file1 file2
Run Code Online (Sandbox Code Playgroud)

我收到以下消息:

join: file1:27497: is not sorted: line_which_was_identified_as_out_of_order
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

(我也尝试对file1进行排序,考虑到整条生产线不仅是该生产线的第一批,而且没有成功)

sort -t\; -c file1不输出任何东西.在第27497行附近,情况确实很奇怪,这意味着排序无法正常工作:

              XYZ113017;...
line 27497--> XYZ11301;...
              XYZ11301;...
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 10

为了补充Wumpus Q. Wumbley从更广泛的角度来看有用的答案(因为我发现这篇文章研究了一个稍微不同的问题).

  • 使用join时,输入文件必须进行排序仅连接字段,否则你可能会看到由OP报告的警告.

有两种常见情况,在排序输入文件时,错误地包含了多个感兴趣的字段:

  • 如果确实指定了一个字段,很容易忘记你还必须指定一个停止字段 - 即使你只定位一个字段 - 因为sort如果只指定了一个起始字段,则使用该行的其余部分; 例如:

    • sort -t, -k1 ... # !! FROM field 1 THROUGH THE REST OF THE LINE
    • sort -t, -k1,1 ... # Field 1 only
  • 如果您的排序字段是输入中的FIRST字段,则很难指定任何字段选择器.

    • 但是,如果字段值可以是彼此的前缀子字符串,则排序整行不会(必然)产生与第1字段排序相同的排序顺序:
    • sort ... # NOT always the same as 'sort -k1,1'! see below for example

陷阱的例子:

#!/usr/bin/env bash

# Input data: fields separated by '^'.
# Note that, when properly sorting by field 1, the order should
# be "nameA" before "nameAA" (followed by "nameZ").
# Note how "nameA" is a substring of "nameAA".
read -r -d '' input <<EOF
nameA^other1
nameAA^other2
nameZ^other3
EOF

# NOTE: "WRONG" below refers to deviation from the expected outcome
#       of sorting by field 1 only, based on mistaken assumptions.
#       The commands do work correctly in a technical sense.

echo '--- just sort'
sort <<<"$input" | head -1 # WRONG: 'nameAA' comes first

echo '--- sort FROM field 1'
sort -t^ -k1 <<<"$input" | head -1 # WRONG: 'nameAA' comes first

echo '--- sort with field 1 ONLY'
sort -t^ -k1,1 <<<"$input" | head -1 # ok, 'nameA' comes first
Run Code Online (Sandbox Code Playgroud)

说明:

  • 当不限制排序到第一个字段时,它是字符的相对排序顺序.^A(列索引6)在这个例子中很重要.换句话说:将字段分隔符与数据进行比较,数据是问题的根源:^具有比其更高的ASCII值A,因此 "A" 之后排序,导致行在nameAA^排序之前开始排序nameA^.

  • 注意:根据区域设置和字符集设置和/或使用的实现,问题可能在一个平台上浮出水面,但在另一个平台上隐藏sort ; 例如,使用有效的区域设置en_US.UTF-8,,作为分隔符和-允许的内部字段:

    • sort在OSX 10.10.2(旧的 GNU sort版本,5.93)上使用,之前排序-(符合ASCII值)
    • sort在Ubuntu 14.04(GNU sort8.21)上使用的相反:-[1]之前排序,

[1]我不知道为什么 - 如果有人知道,请告诉我.测试用sort <<<$'-\n,'


小智 9

sort -k1使用从字段1开始的所有字段作为键.您需要指定一个停止字段.

sort -t\; -k1,1
Run Code Online (Sandbox Code Playgroud)