diff --git a/src/uu/join/src/join.rs b/src/uu/join/src/join.rs index 49698eb511f..b10c5be14ca 100644 --- a/src/uu/join/src/join.rs +++ b/src/uu/join/src/join.rs @@ -320,25 +320,20 @@ impl Input { } } + /// Compare two join fields. Like `sort -k`, a field missing from a line + /// that is too short compares as an empty field. fn compare(&self, field1: Option<&[u8]>, field2: Option<&[u8]>) -> Ordering { - if let (Some(field1), Some(field2)) = (field1, field2) { - if self.ignore_case { - let field1 = CaseInsensitiveSlice { v: field1 }; - let field2 = CaseInsensitiveSlice { v: field2 }; - field1.cmp(&field2) - } else if self.use_locale { - locale_cmp(field1, field2) - } else { - field1.cmp(field2) - } + let field1 = field1.unwrap_or_default(); + let field2 = field2.unwrap_or_default(); + + if self.ignore_case { + let field1 = CaseInsensitiveSlice { v: field1 }; + let field2 = CaseInsensitiveSlice { v: field2 }; + field1.cmp(&field2) + } else if self.use_locale { + locale_cmp(field1, field2) } else { - match field1 { - Some(_) => Ordering::Greater, - None => match field2 { - Some(_) => Ordering::Less, - None => Ordering::Equal, - }, - } + field1.cmp(field2) } } } diff --git a/tests/by-util/test_join.rs b/tests/by-util/test_join.rs index c551196f738..d243cf8e2a3 100644 --- a/tests/by-util/test_join.rs +++ b/tests/by-util/test_join.rs @@ -911,3 +911,29 @@ fn test_operand_count() { .stderr_contains("join: extra operand 'fields_3.txt'\n") .stderr_contains("--help"); } + +#[test] +fn test_missing_key_is_empty_key() { + // Like `sort -k`, a line too short to have the join field has an empty key. + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + at.write("short", "x,\ny\nbob,1002\n"); + at.write("keys", "1002\n"); + ts.ucmd() + .args(&["-t", ",", "-1", "2", "--check-order", "short", "keys"]) + .succeeds() + .stdout_only("1002,bob\n"); + + // ...and pairs with lines whose join field is empty. + ts.ucmd() + .args(&["-t", ",", "-j", "2", "short", "short"]) + .succeeds() + .stdout_only(",x,x\n,x,y\n,y,x\n,y,y\n1002,bob,bob\n"); + + // Same with the default blank separator and a trailing blank. + at.write("blank", "a \nb\nbob 1002\n"); + ts.ucmd() + .args(&["-1", "2", "--check-order", "blank", "keys"]) + .succeeds() + .stdout_only("1002 bob\n"); +}