如何使用 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
:
我有一个文件,其中每行的第 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
: