使用sed,我只想在行中打印一些字符串



我有一个文件,其中包含以下数据。我只想用:分隔ownerIdprofileID的值。

我的文件:

ObjectId("57a046a06f858a9c73b3468a"), "ownerId" : "923003345778", "profileId" : "FreeBundles,LBCNorthParentOffer", "instanceId" : null, "queuedFor" : "unassigned", "state" : "active", "createDateTime" : 1470121632, "startDateTime" : 1470121632, "expireDateTime" : 1485673632, "removeDateTime" : 1487747232, "extensionDateTime" : null, "cancelled" : false, "mode" : "onceOff", "nextMode" : "none", "profileData" : { "serviceProfileId" : "ecs19", "counter" : 1 } }
ObjectId("57a046a06f858a9c73b34688"), "cancelled" : false, "createDateTime" : 1470121632, "expireDateTime" : 1557514799, "extensionDateTime" : null, "instanceId" : null, "mode" : "onceOff", "nextMode" : "none", "ownerId" : "923003345778", "profileData" : { "serviceProfileId" : "ecs19", "counter" : 1 }, "profileId" : "Prov3G,HLRProv", "queuedFor" : "unassigned", "removeDateTime" : 1557514799, "startDateTime" : 1470121632, "state" : "active" }
ObjectId("56d48bd38a8b93baa708fcfa"), "ownerId" : "923003309452", "profileId" : "DiscountOnUsage,Segment04", "instanceId" : null, "queuedFor" : "unassigned", "state" : "active", "createDateTime" : 1456770003, "startDateTime" : 1456770003, "expireDateTime" : null, "removeDateTime" : null, "extensionDateTime" : null, "cancelled" : false, "mode" : "onceOff", "nextMode" : "none", "profileData" : { "serviceProfileId" : "ecs19", "counter" : 1 } }
ObjectId("560ed95f6ca6e0703cf26fcc"), "cancelled" : false, "createDateTime" : 1443813727, "expireDateTime" : 1544381999, "extensionDateTime" : null, "instanceId" : null, "mode" : "onceOff", "nextMode" : "none", "ownerId" : "923003309452", "profileData" : { "serviceProfileId" : "ecs19", "counter" : 1 }, "profileId" : "Prov3G,HLRProv", "queuedFor" : "unassigned", "removeDateTime" : 1544381999, "startDateTime" : 1443813727, "state" : "active" }

输出:

923003345778 : FreeBundles,LBCNorthParentOffer
923003345778 : Prov3G,HLRProv
923003309452 : DiscountOnUsage,Segment04
923003309452 : Prov3G,HLRProv

如果有人知道的话,也请详细解释一下答案。

$ sed 's/.*ObjectId("([^"]*).*"profileId" *: *"([^"]*).*/1 : 2/' file
57a046a06f858a9c73b3468a : FreeBundles,LBCNorthParentOffer
57a046a06f858a9c73b34688 : Prov3G,HLRProv
56d48bd38a8b93baa708fcfa : DiscountOnUsage,Segment04
560ed95f6ca6e0703cf26fcc : Prov3G,HLRProv

我真的不认为需要任何解释,因为这是非常直接的,但如果你有任何问题,请告诉我。

这是一个相当尴尬的情况,你已经设法让自己陷入其中。

通常,您不希望使用像sed这样的纯文本工具来处理结构化数据您提出的任何解决方案在面对格式更改(如JSON字段之间的空格或换行符)时都会很脆弱,并且某些角落的大小写(如带引号的JSON字符串)很难处理。如果您有JSON,您希望使用JSON工具来处理它。

但是,这里并没有JSON。这是BSON的一个文本表示(可能来自MongoDB),它已经砍掉了一些部分

你真正想做的事

解决这个问题的一个合理方法是让MongoDB为您提供JSON,并让jq之类的东西来进行格式化。一旦您有了一个合适的JSON文件,这将像一样简单

jq -r '"(.ownerId) : (.profileId)"' file.json

mongoexport可能是您在这里的朋友,或者将JSON.stringify()放在MongoDB shell中的查询周围1;这取决于你最初是如何获得这些数据的。这种方法需要保存未被质疑的数据,但无论如何,我怀疑无论是什么让你把BSON切成碎片,都应该用类似的东西来代替,以提高可靠性。

1如果您从MongoDB shell获得数据,您可能需要考虑在那里进行格式化。

如何用sed让自己陷入更深的困境

然而,由于您目前没有合适的JSON,您可能想尝试用sed破解自己。这是一个糟糕的想法,我再怎么强调也不为过,因为您从未想要在生产环境中这样做如果你这样做,你将比以前陷入更深的混乱,这种恶性循环不是一个愉快的地方。

所以,我要向你展示的是那种你匆忙中一次性做的事情,并且永远不会再使用,因为你承诺下次会做得很好。您需要仔细检查结果现在:

sed 'h;/^.*"profileId"[[:space:]]*:[[:space:]]*"([^"]*)".*/!d;s//1/;x;/^.*"ownerId"[[:space:]]*:[[:space:]]*"([^"]*)".*/!d;s//1/;G;s/n/ : /' file.bsonish

这对输入数据做出了以下假设:

  1. 每行一个完整对象。放错地方的新线会打破这一局面
  2. ownerIdprofileID字段中没有"

此外,它不会识别损坏的数据,这始终是一个不错的功能。从好的方面来说,它不要求ownerIdprofileId字段以任何特定的顺序出现。

它的工作原理如下:

# Save a copy of the input data; we'll isolate the fields separately.
h
# See if there's a profileId field. If not, the line is silently dropped.
/^.*"profileId"[[:space:]]*:[[:space:]]*"([^"]*)".*/!d
# Isolate that profileId field. // in this context means: reuse the last
# regex (the big one)
s//1/
# Now swap in the saved input data. We'll get ownerId next.
x
# Isolate ownerId as before. If there is no ownerId field, drop line silently.
/^.*"ownerId"[[:space:]]*:[[:space:]]*"([^"]*)".*/!d
s//1/
# append profileId field in hold buffer to what we have
G
# Replace the newline between the two with a colon and some spaces.
s/n/ : /

最新更新