Bash:将行转换为数组元素

Bash:将行转换为数组元素

我在 macOS 系统上有以下格式的 log.txt:

#State:      a           b        c
State 1:118.851979 120.668604 84.472229
State 2:126.789728 149.506520 103.196917
State 3:126.379687 149.382354 104.504792
State 4:126.989312 149.372811 103.499396
State 5:126.330563 149.373374 103.956438
State 6:127.238791 149.458749 103.198541
State 7:125.263833 132.658750 88.320687
State 8:126.828000 148.570000 98.722229
State 9:125.042667 147.087896 98.871813
State 10:124.392521 148.656792 103.744938
State 11:115.969084 131.787022 91.721250
State 12:125.385521 135.633751 91.044167
State 13:125.046354 149.432500 104.132167
State 14:126.368354 149.454480 103.942208
State 15:126.454229 149.583730 104.462458
State 16:114.102083 134.422916 93.555625
State 17:127.905604 138.012417 85.556396
State 18:126.362271 149.187688 104.087229
State 19:115.580250 133.450563 93.011062
State 20:125.555854 133.653730 88.441501

我需要一些线性解决方案,它将其转换为类似 python 的数组格式,类似于:

[[118.851979, 120.668604, 84.472229],[126.789728, 149.506520, 103.196917]...[125.555854, 133.653730, 88.441501]]

因此,我从每一行(2,3 和 4 列)中取出每 3 个数字,并将它们排列在一个 [] 元素中:

[[a, b, c],[a, b, c],[a, b, c]..[a, b , c]]

答案1

一种awk方法:

$ awk -F'[ :]' 'BEGIN{printf "["}NR>1{printf "[%s,%s,%s],",$3,$4,$5}END{printf "]\n"}' file | sed 's/,\]$/]/'
[[118.851979,120.668604,84.472229],[126.789728,149.506520,103.196917],[126.379687,149.382354,104.504792],[126.989312,149.372811,103.499396],[126.330563,149.373374,103.956438],[127.238791,149.458749,103.198541],[125.263833,132.658750,88.320687],[126.828000,148.570000,98.722229],[125.042667,147.087896,98.871813],[124.392521,148.656792,103.744938],[115.969084,131.787022,91.721250],[125.385521,135.633751,91.044167],[125.046354,149.432500,104.132167],[126.368354,149.454480,103.942208],[126.454229,149.583730,104.462458],[114.102083,134.422916,93.555625],[127.905604,138.012417,85.556396],[126.362271,149.187688,104.087229],[115.580250,133.450563,93.011062],[125.555854,133.653730,88.441501]]

或者,更清晰一点:

awk -F'[ :]' 'BEGIN{
                printf "["
              }
              NR>1{
                printf "[%s,%s,%s],",$3,$4,$5
              }
              END{
                printf "]\n"
              }' file | sed 's/,\]$/]/'

解释

  • awk -F'[ :]':将 awk 的输入字段分隔符设置为空格或 a :
  • BEGIN{printf "["}:打印开头[
  • NR>1{printf "[%s,%s,%s],",$3,$4,$5}:对于除第一行之外的每一行,打印 a 内的第三个、第四个和第五个字段,[ ]并用逗号分隔。
  • END{printf "]\n"}:打印结束语]
  • sed 's/,\]$/]/',:删除END块之前最后添加的内容。

答案2

您可以使用jq将数据格式化为 JSON 数组数组:

jq -nRc '[inputs | split(":")] | .[1:] | map(.[1] | split(" ") | map(tonumber))' <log.txt

如果你想要四舍五入的值,你可以替换

map(tonumber)

map(tonumber | . *1000 | round | . /1000)

IE

$ jq -nRc '[inputs | split(":")] | .[1:] | map(.[1] | split(" ") | map(tonumber | .*1000 |
round | ./1000))' <log.txt
[[118.852,120.669,84.472],[126.79,149.507,103.197],[126.38,149.382,104.505],[126.989,149.373,103.499],[126.331,149.373,103.956],[127.239,149.459,103.199],[125.264,132.659,88.321],[126.828,148.57,98.722],[125.043,147.088,98.872],[124.393,148.657,103.745],[115.969,131.787,91.721],[125.386,135.634,91.044],[125.046,149.433,104.132],[126.368,149.454,103.942],[126.454,149.584,104.462],[114.102,134.423,93.556],[127.906,138.012,85.556],[126.362,149.188,104.087],[115.58,133.451,93.011],[125.556,133.654,88.442]]

答案3

所以......这两个答案都很好,但让我真的很紧张。让我解释。

awk就如它所得到的那样“Unix”。然而,假设你会知道是不明智的哪个“awk”你会得到;所有这些都是非常强大的,但与原始 awk 的扩展非常不兼容(事实上,很可能会得到,但仅限于 Mac),或 gawk、mawk、nawk auk... 或,嗯,perl 之一。仅举几例。

AWK 本身也是完全图灵完备的语言,但它与 shell 命令语言(即您所说的“bash”)有点太像了,我不太喜欢为这样的东西调用内联。一个放错位置的单引号突然间你的 AWK 命令在 shell 中执行,但做了完全不同的事情。它也有点重磅什么像这样的相对简单的任务... AWK 本身可以执行嵌套关联数组,并且具有可以对本机 32 位浮点数执行的本机三角函数。不需要Python。

解决办法jq惊人的...我觉得自己很愚蠢——我完全没有意识到jq有能力读入其原生 JSON 就像它可以读取的那样出去...但当然可以!我不知道什么jq 不能做...我最近使用了一个包装器,我忘记了它叫什么,它能够使用相同的符号轻松安全地处理 XML Xpath,然后以 YAML 形式返回键值反转的相同数据。惊人的。然而,jq它是一个基本上基于JSON—(道格拉斯·克罗克福德发明的一种数据序列化格式),它听起来同样不怎么样确切地就像你正在寻找的那样: 1.虽然它们看起来很相似,但Python数据结构是不是JSON,如果你想在Python中安全地处理JSON,你需要使用该json模块来确保反序列化得到正确处理。等等。在像这样的 JSON 嵌套括号中,[[],]与 Python 中的含义完全不同:它是 JavaScript 中显式表达的一种方式目的注释“这是具体来说一个带有嵌套数组的数组,而不是对象,使用大括号,,{}而不是方括号,[]。例如,它也不会处理最后一个嵌套数组后面的悬挂逗号;而 Python 通常会。

如果这个问题只是关于文本处理,正如它所标记的那样,这就是我要指出的地方几乎全部现代 shell 可以完成这种类型的文本处理,而无需调用单个外部程序 - 您可以将文件通过管道传输到read内置函数,该内置函数将单个变量作为参数(通常在循环中使用while,该变量传统上称为line,即while read line < file; do) ,然后在您的 do 块中,您可以通过将其作为参数传递给函数来对每一行进行字段分割,该函数会将其视为特殊变量$@及其组件$1,,$2...$3等。如果您不希望它字段拆分,您可以使用$*.实际上,这(通常)是 shell 拥有的唯一复杂数据类型;它不知道或不将任何东西视为数字,除非使用(基本的)算术扩展,它看起来像$(($x + 4)),或者通过调用外部或工具或扩展。

但似乎并非如此你所问的问题,我认为上面最好的“答案”来自@thanasisp,我将其解释为“如果这将在Python中使用,你为什么不只使用Python?”或者“类似 python 的数组格式”到底是什么意思?

首先,“类似Python的数组格式”这个短语或多或少没有意义。虽然嵌套括号与逗号格式可以被宽松地称为C-喜欢 (C是它的来源语言,以及为什么它存在于 Python、JSON 和许多其他语言中),每种语言(或序列化格式)在实现上都有许多微妙但非常重要的差异。此外,除了 Python 之外,没有其他语言或语言功能我可以称之为“类似 Python”。 Python 也是唯一一种我认为也被称为“相当”的语言不像Python,因为 Python 与 Python 完全不兼容,这取决于你指的是今天所谓的“Python 2”,它在很大程度上已被禁止/强制弃用,还是当前的“Python”,最初是一个分支,被称为Python 3000、Py3k、Python3,但已经(经过多年的激烈争论,通常是“Python”的含义。

最关键的是,在所有版本的 Python 中,您都指定了完全有效的数据,例如“1:118.851979”,这是一种完全有效的构造……但它并没有达到我认为您想要的效果;冒号是“切片”运算符。然而,在Python中,像在其他结构化变量赋值中那样隐式内联操作通常是完全可以接受的,并且通常也可以在其他地方内联代码。然而,在其他语言中,这可能被解释为一个比率的数字;在某些(C++ 等)中,冒号表示对象或模板选择器,在 shell 中,它是 null 函数。此外,您引用的例子也完全有效,但我再次相信这意味着与我假设的完全不同的东西实际上Mean——[[a, b, c],[a, b, c],[a, b, c]...是一个由对三个先前定义的变量(名为“a”、“b”或“c”)的引用组成的结构,后面跟着连续两个对这些相同变量的引用。那是什么意思?

你有的例子我知道这可能会被认为但是他们真的

相关内容