【问题标题】:Sed isn't replacing all occurrences of string in fileSed 没有替换文件中所有出现的字符串
【发布时间】:2023-03-15 20:44:02
【问题描述】:

编辑:我正在使用 Cygwin。我不确定这是否相关,这是我在写这个问题时遗漏的一个细节。

EDIT2:已尝试用 RegEx \s 替换人们指出的“TAB”字符,它涵盖了间距字符(主要是空格和制表符),这根本不影响表达式,这意味着它不是导致问题,特别是因为表达式运行一次而没有错误。

到目前为止,这个脚本给我带来了很多麻烦。

我之前确实遇到过问题,但我在这里写问题时解决了这个问题(幸运的 imo),但这个问题我已经坚持了至少一个小时,我尝试了不同的解决方案,但没有一个实际工作或告诉我一些我尚未尝试过的事情。

我有一个看起来很酷的 FTP 日志提取器脚本,该脚本的一部分将该日志文件中的 600MB 错误替换为空,基本上将它们删除。不幸的是,这个脚本也消除了部分其他错误,所以我不得不编辑它。这就是我卡住的地方。

通过基础研究,我发现sed 可以做我想做的事,并且通过三个小时的游戏到目前为止,它完成了我告诉它的大部分事情,减去一件事。尽管在末尾附加了g 修饰符,但我构建的sed 语句中的一个也是唯一一个仅替换了我给它的字符串的第一个实例。

我现在正在使用一个测试脚本,以避免对我的原始 FTP 脚本造成潜在的永久性损坏,并且该测试脚本复制了一个示例文件,其中包含一些我需要替换的错误。

在显示之前的脚本 INTENDED 行为演练: 1. 设置文件中所有行的前缀,脚本中非常重要的部分。 2. 将示例文件复制到名为 test2.log 的文件中 3. 将 UNIX 换行符 \n 的所有实例替换为 [loll](我想到的第一件事) 4. 删除所有战斗错误类型 1 和 2 的实例。 5. 返回所有带有 UNIX \n 换行符的 [loll] 字符串,因此将日志文件返回到其原始状态减去错误。

脚本:

#DTP="\[([0-9]+-[0-9]+-[0-9]+-[0-9]+|latest)\.log\] \[[0-9]+:[0-9]+:[0-9]+\] \[Server   thread/(INFO|WARN)\]: "
echo "${DTP}"
DTP1="\[[0-9]*:[0-9]*:[0-9]*\]\s\[Server\sThread\/\(WARN\|INFO\)\]:\s"
DTP="\[loll\]\[[0-9]*:[0-9]*:[0-9]*\]\s\[Server\sThread\/\(WARN\|INFO\)\]:\s"
echo "${DTP}"
echo "1"
cp test.log test2.log
#cat test.log >test2.log
sed -i ':a;N;$!ba;s/\n/\[loll\]/g' test2.log #| egrep -i "" >test2.log
sed -i 's/'${DTP1}'Caught error in battle.  Continuing...'${DTP}'java.lang.NullPointerException'${DTP}' at com.pixelmonmod.pixelmon.battles.controller.participants.PixelmonWrapper.useAttack(PixelmonWrapper.java:173)'${DTP}' at com.pixelmonmod.pixelmon.battles.controller.participants.PixelmonWrapper.takeTurn(PixelmonWrapper.java:330)'${DTP}'  at com.pixelmonmod.pixelmon.battles.controller.BattleControllerBase.takeTurn(BattleControllerBase.java:276)'${DTP}' at com.pixelmonmod.pixelmon.battles.controller.BattleControllerBase.update(BattleControllerBase.java:157)'${DTP}'   at com.pixelmonmod.pixelmon.battles.BattleRegistry.updateBattles(BattleRegistry.java:63)'${DTP}'    at com.pixelmonmod.pixelmon.battles.BattleTickHandler.tickStart(BattleTickHandler.java:12)'${DTP}'  at cpw.mods.fml.common.eventhandler.ASMEventHandler_20_BattleTickHandler_tickStart_WorldTickEvent.invoke(.dynamic)'${DTP}'  at cpw.mods.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:51)'${DTP}' at cpw.mods.fml.common.eventhandler.EventBus.post(EventBus.java:122)'${DTP}'    at cpw.mods.fml.common.FMLCommonHandler.onPostWorldTick(FMLCommonHandler.java:255)'${DTP}'  at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:929)'${DTP}'  at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:429)'${DTP}'    at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:776)'${DTP}'  at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:639)'${DTP}'   at java.lang.Thread.run(Thread.java:745)//gI' test2.log
echo "2"
sed -i 's/'${DTP1}'Caught error in battle.  Continuing...'${DTP}'java.lang.NullPointerException\[loll\]//gI' test2.log
echo "3"
sed -i 's/\[loll\]/\n/g' test2.log

我已将它们设置为也对提供的字符串运行不区分大小写的检查,因为有时我使用全小写,但是对于大部分内容,我直接复制并粘贴它。

示例输入: http://pastebin.com/3KPB33X2

输出: 预期:

meow
Test message
WOOF MEOWLOL

实际:http://pastebin.com/pnvDwkxz

这已经让我心烦了一段时间,因为我甚至在另一个问题之前就遇到了这个问题,只是我几乎没有注意到它。我在脚本中找不到任何可预测的行为,据我所知,它应该可以正常工作并给我期望的输出。

任何帮助将不胜感激,因为一旦我能解决这个错误,我就可以输入脚本的其余部分,并用我的日志提取器中现有的战斗错误替换脚本替换它。

知道我这是一件小而愚蠢的事情,但我已经尝试了我遇到的所有事情,包括将 :a;N;$!ba; 添加到无法正常工作的位的开头(并意识到这非常失败)。

谢谢。 ~BAI1

【问题讨论】:

  • at 之前似乎有多个空格,或者可能是一个 TAB。尝试在那里使用\s+
  • 所以简而言之,您想删除[00:00:00] [Server thread/INFO]: Caught error in battle. Continuing... 以及之后的所有错误行,不是吗?
  • @Barmar,我重写了整个脚本,以确保在我在这里发布之前它不是语法错误,包括“at”之前的制表符/空格的可能性。我仔细检查了日志,它实际上是“at”之前的一个选项卡,使用选项卡不会在第一个错误删除实例中引起问题。
  • @CasimiretHippolyte,正是这样。有三种不同类型的战斗错误,但其中较大的一种是主要的。一旦我们发现为什么它没有按预期工作,我可以稍后再做第三个。
  • 另外,双方和其他人都注意到第二个表达式可以完美运行,除非被打断,然后错过一步并照常继续。示例输出:pastebin.com/bgcBJiTN 和我输入的内容:pastebin.com/DrZA8yLS

标签: regex bash sed cygwin


【解决方案1】:

您是否正在寻找这样的东西:

sed -n ':a;s/\[.*Server thread\/\(INFO\|WARN\).*//i;/^$/!p;n;b a' battle.log 

【讨论】:

  • 解释当捕获 [Server thread/INFO] 和 [Server thread/WARN] 的语法已经完全按预期工作时,这是如何相关的。我的问题是它不会尝试在中断后替换文件中特定错误的更多实例(类型一,较大的 Sed 表达式),例如:一个错误结束与另一个错误开始之间的文本。
  • @BAI1:这个 sed 命令替换了所有脚本。如果不是你想要的,试着给出一个更有代表性的示例文件。
  • 我不想替换文件中的所有 [Server thread/INFO] 或 [Server thread/WARN] 语句。抱歉,如果我说的话可能会让人觉得不尊重,尽管我想要的是一个脚本来删除我的示例输入文件 pastebin.com/3KPB33X2 中的所有错误,但没有别的。
  • 打算编辑我​​的上述 cmets 之一,我不想在出现上述两个字符串中的任何一个后删除所有行。很抱歉造成混乱。
  • @BAI1:不客气。主要问题是您没有解释为什么应该或不应该删除行或子字符串,标准是什么?您的原始脚本显然太复杂了,不是解决方案。一个包含 15 行字面意思的 sed 命令,这太疯狂了。所以,如果你解释一下你是如何知道必须删除一行的,那将有可能对你有所帮助。否则,您会发现很少有人有兴趣在长脚本中调试错误方法并且处理大量数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 2018-06-25
  • 2019-01-10
  • 2018-07-11
  • 2011-06-08
相关资源
最近更新 更多