交换显示公共字符串的两个连续行的位置

Opu*_*num 3 scripting terminal

我有一个文本文件大约。1200 万行,每行由 4 个字段组成(第 1、2、3 和 4 列)

大多数行在第 2 列中都有一个唯一的 STRING。我不想修改这些行中的任何一行。

在文本文件中,我经常在第 2 列中有 2 行具有相同 STRING 的连续行。这在整个文本文件中大约发生 10,000 次。一个例子如下所示:

column1 column2 column3 column4  
WT 1 ILS G  
WT 2 DSG E          
WT 3 WYT S 
. . . .  
WT 106  AAA X  
WT 106  BBB Y  
. . . .  
WT 2704 CCC X  
WT 2704 DDD Y   
. . . .  
Run Code Online (Sandbox Code Playgroud)

我想达到的目标:

column1 column2 column3 column4  
WT 1 ILS G  
WT 2 DSG E          
WT 3 WYT S 
. . . .  
WT 106  BBB Y    
WT 106  AAA X  
. . . .   
WT 2704 DDD Y   
WT 2704 CCC X  
. . . .   
Run Code Online (Sandbox Code Playgroud)

我有什么资源?

我有一个包含 10,000 个字符串的文本文件,它们出现两次(在我的示例中为 106 和 2704),我需要交换两行。我也知道 X 和 Y 在 column2 相同的行中总是相同的。

到目前为止我做了什么?

我知道如何用一个公共字符串(我指定的,例如 106)识别两行,并用 sed 交换它们。我不知道如何使它动态化(使用带有 10000 个字符串的文本文件来识别),所以我不必单独启动 10000 个命令。

提前感谢您的时间和帮助。最好的事物,

洛朗

Pau*_*ant 5

awk 中的蛮力方法:总是保存一行,并提升在字段 1 中匹配它的任何后续行。

我测试了一百万行(一次交换),它运行了 5.5 秒,所以你的运行应该刚好超过一分钟。它不需要您的参考文件。

脚本,包括带有测试行的 HereDoc。

#! /bin/bash

awkPairs () {

    local Awk='
FNR == 1 { k = $2; x = $0; next; } 
$2 != k { print x; k = $2; x = $0; next; } 
{ print $0; }
END { print x; }
'
    awk -f <( printf '%s' "${Awk}" ) -
}

    [ x ] && time awkPairs <<'[][]'
WT 1 One x1
WT 2 Two x2
WT 3 Three_1 x3
WT 3 Three_2 y3
WT 4 Four x4 
WT 5 Five_1 x5
WT 5 Five_2 y5
[][]
Run Code Online (Sandbox Code Playgroud)

(短)测试运行。

$ ./awkPairs
WT 1 One x1
WT 2 Two x2
WT 3 Three_2 y3
WT 3 Three_1 x3
WT 4 Four x4
WT 5 Five_2 y5
WT 5 Five_1 x5

real    0m0.009s
user    0m0.004s
sys     0m0.006s
Run Code Online (Sandbox Code Playgroud)

删除了所有测试材料的脚本。它可以使用单个参数(输入文件的名称)调用,也可以使用重定向或管道输入的标准输入进行调用。输出始终发送到 stdout。

#! /bin/bash

awkPairs () {

    local Awk='
FNR == 1 { k = $2; x = $0; next; }
$2 != k { print x; k = $2; x = $0; next; }
{ print $0; }
END { print x; }
'
    awk -f <( printf '%s' "${Awk}" ) "${1:--}"
}

    awkPairs "${1}"
Run Code Online (Sandbox Code Playgroud)

所以它可以通过以下任何一种方式调用:

./awkPairs myData.txt
./awkPairs < myData.txt
cat myData.txt | ./awkPairs
Run Code Online (Sandbox Code Playgroud)