bash - AWK 在单行中传递多个命令
问题描述
我想将以下多个 awk 命令组合成一个 awk 程序:
awk -F 'FS' '{ $1 = ($1 == "}" ? "" : $1) } 1' sorce > destfil
awk -F 'FS' '{ $3 = ($3 == "]" ? "" : $3) } 1' sorce > destfil
awk -F 'FS' '{ $5 = ($5 == "}" ? "}," : $5) } 1' sorce > destfil
我曾尝试使用来完成此操作&&
,但结果不是我所期望的。
awk -F 'FS' '{ $1 = ($1 == "}" ? "" : $1) && $3 = ($3 == "]" ? "" : $3) && $5 = ($5 == "}" ? "}," : $5) } 1' sorce > destfil
输出中似乎有各种零。
问题:
- 如何合并这些行?
- 零的起源是什么?
谢谢!
@RavinderSingh13,当我尝试您的代码、示例输入文件和输出文件时,如下所示
[user@restt]$ tail source
{
}
]
}
{
" e t
{
}
]
}
[user@test]$ awk -F 'FS' '{$1=($1=="}"?"":$1); $3=($3=="]" ? "" : $3) ; $5=($5=="}" ? "}," :$5);} 1' source > target
[user@test]$ tail target
{
}
]
}
{
" e t
{
}
]
}
我认为这个问题与字段分隔符 -F 'FS' 有关,或者我不确定。
@kvantour,下面我给出了我的示例输入文件和命令我正在运行什么我得到什么输出我需要什么。
源文件内容:
{
"metadata": [
{
sample content line 1
sample content line n
}
]
}
{
"metadata": [
{
sample content line 1
sample content line n
}
]
}
{
"metadata": [
{
sample content line 1
sample content line n
}
]
}
{
"metadata": [
{
sample content line 1
sample content line n
}
]
}
我正在运行的命令
$ awk '($1=="}"){$1="First Column"}
($3=="]"){$3="third Column"}
($5=="}"){$5="Fifth Column"}
{$1=$1}1' sample.json > out
我得到的输出:
[root@centos-src ~]# cat out
{
"metadata": [
{
sample content line 1
sample content line n
First Column
]
First Column
{
"metadata": [
{
sample content line 1
sample content line n
First Column
]
First Column
{
"metadata": [
{
sample content line 1
sample content line n
First Column
]
First Column
{
"metadata": [
{
sample content line 1
sample content line n
First Column
]
First Column
但我期望输出是:
{
"metadata": [
{
sample content line 1
sample content line n
Fifth Column
third Column
First Column
{
"metadata": [
{
sample content line 1
sample content line n
Fifth Column
third Column
First Column
{
"metadata": [
{
sample content line 1
sample content line n
Fifth Column
third Column
First Column
{
"metadata": [
{
sample content line 1
sample content line n
Fifth Column
third Column
First Column
解决方案
在一个不错的 awk 结构中,可以这样写:
awk -F 'FS' '($1=="}"){$1=""}
($3=="]"){$3=""}
($5=="}"){$5="},"}
{$1=$1}1' <file>
我添加$1=$1
到列表中的原因是在不满足上述条件的情况下重新处理$0
正确。OFS
如果您不这样做,您将打印出FS
作为字段分隔符的行,而其他行将打印为OFS
.
那么为什么你会得到一堆零呢?
让我们看看你的单线:
$1 = ($1 == "}" ? "" : $1) && $3 = ($3 == "]" ? "" : $3) && $5 = ($5 == "}" ? "}," : $5)
并通过假设括号之间的三元运算符返回一个变量来简化它。所以我们可以将其重写为:
$1 = var1 && $3 = var3 && $5 = var5
考虑到:
expr1 && expr2
的优先级高于value = expr
。lvalue = expr
返回 expr 的值
我们可以看到 awk 将其解释为
$1 = var1 && ($3 = (var3 && ($5 = var5) ) )
所以结果将是:
$5 = var5
$3 = var3 && $5 equalling var3 && var5
$1 = var1 && $3 equalling var1 && var5
这在以下示例中可见:
$ echo "a b c d e f" | awk '{ $1="p" && $3 = "q" && $5 = "r"}1'
1 b 1 d rf
最后,在awk
空字符串和数字零中,逻辑值false和其他任何值true。因此,由于您的两个原始三元运算符可以返回空字符串,它们将确保逻辑 AND 将返回 false,这相当于数字零。因此,如果原始等于,则$1
和$3
都将与零匹配$3
]
更新(收到 [mcve] 后)
你试图达到的目标并不是那么容易。首先,您似乎假设列号意味着行中的字符号。可悲的是,情况并非如此。在默认模式下,awk 假定字段$n
是n
行中的第一个单词,其中单词是不包含任何空格的字符序列。所以在下面的文字中,
}
]
}
所有字符实际上都由$1
.
在您的 JSON 文件完全缩进的假设下,可以使用以下内容:
awk '/^} *$/{$0="First Column"}
/^ ] *$/{$0=" Thrid Column"}
/^ } *$/{$0=" Fifth Column"}
{print $0}' <file>
但是,如果您的 JSON 文件没有统一缩进,事情就会变得相当混乱。最简单的方法是首先使用jq
as解析文件
jq . <json-file> | awk ...
推荐阅读
- php - WP All Import Pro 功能更改日期和时间格式(从导入的 .CSV)
- php - Laravel custom unique validation with Rule
- html - Angular Material Tab - How to change label font size
- python-3.x - What to do when python don't want to run a previous working program?
- mysql - Required context properties mismatch in connecting the flink with mysql database
- c - 两个假定相同的变量以某种方式持有不同的值
- ios - [iOS][FoursquareAPI] ERROR: [connection] nw_resolver_start_query_timer_block_invoke
- reactjs - 如何更改反应选择上的下拉指示器位置
- java - Spring Scheduler:在使用 cron 和启动时运行一次之间切换
- javascript - html 无法在 python 烧瓶网站上正确呈现