如何使用 Shell 脚本交换文件中符合条件的行

How to swap the lines in a file that match a condition using Shell script

我有一个文件,其中每行的第 28 个字符是 "A" 或 "D"。 我想以文件第一行的第 28 个字符为 "D" 和 文件的第二行应该有 28 个字符 "A"。 并且该模式应贯穿整个文件。

输入文件:

00254920141228N201412251850A201412241740SA1118WE1440SCL
00254920141228N201412251850D201412200050SA1150TH1850000
00254920141228R201412251850A201412241740SA1118WE1440SCL
00254920141228R201412251850A201412241740SA1118WE1440SCL
00254920141228R201412251850D201412200050SA1150TH1850000
00254920141228R201412251850D201412200050SA1150TH1850000

输出应该是:

00254920141228N201412251850D201412200050SA1150TH1850000
00254920141228N201412251850A201412241740SA1118WE1440SCL
00254920141228R201412251850D201412200050SA1150TH1850000
00254920141228R201412251850A201412241740SA1118WE1440SCL
00254920141228R201412251850D201412200050SA1150TH1850000
00254920141228R201412251850A201412241740SA1118WE1440SCL

我想用 Unix shell 脚本编写脚本。

这是一个简单的 Python 脚本,它实现了我认为您想要描述的内容。

from sys import stdin
keep = "A"
kept = []
for line in stdin:
    line = line.rstrip("\r\n")
    pattern = line[27:28]
    # print("## keep %s, pattern %s, %s" % (keep, pattern, line))
    if pattern != keep:
        if len(kept) > 0:
            print line
            # print("### len kept == %i, popping" % len(kept))
            print kept.pop(0)
        else:
            # print("### no kept, just print")
            print line
            keep = pattern
    else:
        # print("### keeping for later")
        keep = pattern
        kept.append(line)
if len(kept) > 1:
    raise ValueError("Too many %s lines" % keep)
elif len(kept) == 1:
    print kept[0]

我留下了我的调试打印,这样你就可以看到发生了什么 -- 取消注释带有 # 的打印语句,如果它没有完全按照你的要求进行调试,可以获得一些调试诊断。

实际上,为了简单起见,我开始将其编写为 Awk 脚本,但 Awk 数组没有 push/pop,所以结果比我喜欢的要复杂。

我不会为此使用 sed。我不怀疑它是可行的,但它很难维持,特别是如果你和你的所有同事都没有致力于保持 sed 的高度流畅。 (这样说更好 "write-only language"...)

我一直对所有 Python 字符串使用双引号。这样,您可以将其单引号嵌入到一个简单的 shell 脚本中进行测试,如下所示:

#!/bin/sh
python -c '... text
of
script' <<':'
sample
data
: