将 awk 输出用于条件语句
Using awk output for conditional statement
我有一些数据格式如下:
2 1 500 500 500
3 1 500 500 500
6 1 500 500 500
8 1 500 500 500
9 1 500 500 500
11 1 500 500 500
12 1 500 500 500
14 1 500 500 500
15 1 500 500 500
16 1 500 500 500
17 1 500 500 500
20 1 500 500 500
21 1 500 500 500
23 1 500 500 500
24 1 500 500 500
25 1 500 500 500
27 1 500 500 500
30 1 500 500 500
31 1 500 500 500
32 1 500 500 500
33 1 500 500 500
34 1 500 500 500
35 1 500 500 500
38 1 500 500 500
40 1 500 500 500
41 1 500 500 500
43 1 500 500 500
44 1 500 500 500
46 1 500 500 500
47 1 500 500 500
我只想将第 1 列等于 11-40 的行中的 500 个值更改为 100。现在我正在做类似的事情:
Numbers=($(seq 11 1 40))
File=filename.txt
for i in ${Numbers[*]}
do
if [ $i == awk '{print }' $File ];then
NumberLine=$(grep -n $i $File | cut -d : -f 1)
sed -i "${NumberLine}s/500/100/" $File
fi
done
单独来看,每一行似乎都在做我想做的事情,但是当我将它们放入循环中时,出现以下错误:
./changeRestraints.sh: line 5: [: too many arguments
我怀疑这与我的 awk 作为条件语句的一部分有关。我该如何解决这个问题才能制作这个脚本 运行?
谢谢,
为了提高效率,在循环中重复调用 awk
和 sed
不是一个好主意。请尝试:
awk '>10 && <=40 {gsub(/\<500\>/, "100")} 1' filename.txt
请注意正则表达式 \<
和 \>
是匹配单词边界的 GNU awk
扩展。
[编辑]
gsub()
函数是 sub()
的变体,它替换了多个
匹配字符串的出现,而 sub()
替换第一个
仅匹配。 sub()
和 gsub()
之间的关系类似于
s/regex/repl/
和 s/regex/repl/g
在 sed
.
如果你想为嵌入的数字使用变量,你可以
利用可以分配 awk 变量的 -v varname=value
机制
通过命令行选项:
#!/bin/bash
start=11 # bash variables
stop=40
from=500
to=100
awk -v start="$start" -v stop="$stop" -v from="$from" -v to="$to" '>=start && <=stop {gsub("\<" from "\>", to)} 1' filename.txt
- 赋值
-v start="$start"
时,lhsstart
是一个awk变量名
rhs "$start"
是一个 bash 变量。我们可以使用相同的名称
他们(尽管他们看起来很混乱)。您还可以分配变量
立即值,例如 -v start=11
.
- 因为我们不能使用正则表达式引用
/regex/
来包含 awk 变量,
我们需要说 "\<" from "\>"
来代替。中间的空格
只是为了可读性,它等同于 "\<"from"\>"
.
您从未真正执行过 awk
。您将 $i
与字符串 awk 进行比较,然后 test 命令会找到它无法处理的其他参数。因此,您会收到 参数过多 错误。
您需要 运行 awk
才能获得其输出,例如通过执行
if [ "$i" = "$(awk ... )" ]
then
...
您也可以使用 sed
,其中模式 ^(40|[23][0-9]|1[1-9])[[:space:]]
匹配数字 11-40,后跟字符串开头的 space。
sed -E '/^(40|[23][0-9]|1[1-9])[[:space:]]/s/500/100/g' file
输出
2 1 500 500 500
3 1 500 500 500
6 1 500 500 500
8 1 500 500 500
9 1 500 500 500
11 1 100 100 100
12 1 100 100 100
14 1 100 100 100
15 1 100 100 100
16 1 100 100 100
17 1 100 100 100
20 1 100 100 100
21 1 100 100 100
23 1 100 100 100
24 1 100 100 100
25 1 100 100 100
27 1 100 100 100
30 1 100 100 100
31 1 100 100 100
32 1 100 100 100
33 1 100 100 100
34 1 100 100 100
35 1 100 100 100
38 1 100 100 100
40 1 100 100 100
41 1 500 500 500
43 1 500 500 500
44 1 500 500 500
46 1 500 500 500
47 1 500 500 500
gawk 中的另一种方法:
gawk '~/1[1-9]|[23][0-9]|40/{ ===100 }1' file
当您要保留空格时:
gawk '~/1[1-9]|[23][0-9]|40/{ gsub(/\<500\>/,"100") }1' file
使用 sed
sed -i '/^11/,/^40/s/500/100/g' filename.txt
可能是这样的:
mawk 'gsub("500", (_=+)<11 || (40<_) ? "&" : "100")'
2 1 500 500 500
3 1 500 500 500
6 1 500 500 500
8 1 500 500 500
9 1 500 500 500
11 1 100 100 100
12 1 100 100 100
14 1 100 100 100
15 1 100 100 100
16 1 100 100 100
17 1 100 100 100
20 1 100 100 100
21 1 100 100 100
23 1 100 100 100
24 1 100 100 100
25 1 100 100 100
27 1 100 100 100
30 1 100 100 100
31 1 100 100 100
32 1 100 100 100
33 1 100 100 100
34 1 100 100 100
35 1 100 100 100
38 1 100 100 100
40 1 100 100 100
41 1 500 500 500
43 1 500 500 500
44 1 500 500 500
46 1 500 500 500
47 1 500 500 500
如果您更喜欢基于 FS + OFS
的方法,那么
mawk 'NF *= (OFS = (_=+)<11||(40<_) ? FS : __)^!__' FS='500' __='100'
我有一些数据格式如下:
2 1 500 500 500
3 1 500 500 500
6 1 500 500 500
8 1 500 500 500
9 1 500 500 500
11 1 500 500 500
12 1 500 500 500
14 1 500 500 500
15 1 500 500 500
16 1 500 500 500
17 1 500 500 500
20 1 500 500 500
21 1 500 500 500
23 1 500 500 500
24 1 500 500 500
25 1 500 500 500
27 1 500 500 500
30 1 500 500 500
31 1 500 500 500
32 1 500 500 500
33 1 500 500 500
34 1 500 500 500
35 1 500 500 500
38 1 500 500 500
40 1 500 500 500
41 1 500 500 500
43 1 500 500 500
44 1 500 500 500
46 1 500 500 500
47 1 500 500 500
我只想将第 1 列等于 11-40 的行中的 500 个值更改为 100。现在我正在做类似的事情:
Numbers=($(seq 11 1 40))
File=filename.txt
for i in ${Numbers[*]}
do
if [ $i == awk '{print }' $File ];then
NumberLine=$(grep -n $i $File | cut -d : -f 1)
sed -i "${NumberLine}s/500/100/" $File
fi
done
单独来看,每一行似乎都在做我想做的事情,但是当我将它们放入循环中时,出现以下错误:
./changeRestraints.sh: line 5: [: too many arguments
我怀疑这与我的 awk 作为条件语句的一部分有关。我该如何解决这个问题才能制作这个脚本 运行?
谢谢,
为了提高效率,在循环中重复调用 awk
和 sed
不是一个好主意。请尝试:
awk '>10 && <=40 {gsub(/\<500\>/, "100")} 1' filename.txt
请注意正则表达式 \<
和 \>
是匹配单词边界的 GNU awk
扩展。
[编辑]
gsub()
函数是 sub()
的变体,它替换了多个
匹配字符串的出现,而 sub()
替换第一个
仅匹配。 sub()
和 gsub()
之间的关系类似于
s/regex/repl/
和 s/regex/repl/g
在 sed
.
如果你想为嵌入的数字使用变量,你可以
利用可以分配 awk 变量的 -v varname=value
机制
通过命令行选项:
#!/bin/bash
start=11 # bash variables
stop=40
from=500
to=100
awk -v start="$start" -v stop="$stop" -v from="$from" -v to="$to" '>=start && <=stop {gsub("\<" from "\>", to)} 1' filename.txt
- 赋值
-v start="$start"
时,lhsstart
是一个awk变量名 rhs"$start"
是一个 bash 变量。我们可以使用相同的名称 他们(尽管他们看起来很混乱)。您还可以分配变量 立即值,例如-v start=11
. - 因为我们不能使用正则表达式引用
/regex/
来包含 awk 变量, 我们需要说"\<" from "\>"
来代替。中间的空格 只是为了可读性,它等同于"\<"from"\>"
.
您从未真正执行过 awk
。您将 $i
与字符串 awk 进行比较,然后 test 命令会找到它无法处理的其他参数。因此,您会收到 参数过多 错误。
您需要 运行 awk
才能获得其输出,例如通过执行
if [ "$i" = "$(awk ... )" ]
then
...
您也可以使用 sed
,其中模式 ^(40|[23][0-9]|1[1-9])[[:space:]]
匹配数字 11-40,后跟字符串开头的 space。
sed -E '/^(40|[23][0-9]|1[1-9])[[:space:]]/s/500/100/g' file
输出
2 1 500 500 500
3 1 500 500 500
6 1 500 500 500
8 1 500 500 500
9 1 500 500 500
11 1 100 100 100
12 1 100 100 100
14 1 100 100 100
15 1 100 100 100
16 1 100 100 100
17 1 100 100 100
20 1 100 100 100
21 1 100 100 100
23 1 100 100 100
24 1 100 100 100
25 1 100 100 100
27 1 100 100 100
30 1 100 100 100
31 1 100 100 100
32 1 100 100 100
33 1 100 100 100
34 1 100 100 100
35 1 100 100 100
38 1 100 100 100
40 1 100 100 100
41 1 500 500 500
43 1 500 500 500
44 1 500 500 500
46 1 500 500 500
47 1 500 500 500
gawk 中的另一种方法:
gawk '~/1[1-9]|[23][0-9]|40/{ ===100 }1' file
当您要保留空格时:
gawk '~/1[1-9]|[23][0-9]|40/{ gsub(/\<500\>/,"100") }1' file
使用 sed
sed -i '/^11/,/^40/s/500/100/g' filename.txt
可能是这样的:
mawk 'gsub("500", (_=+)<11 || (40<_) ? "&" : "100")'
2 1 500 500 500
3 1 500 500 500
6 1 500 500 500
8 1 500 500 500
9 1 500 500 500
11 1 100 100 100
12 1 100 100 100
14 1 100 100 100
15 1 100 100 100
16 1 100 100 100
17 1 100 100 100
20 1 100 100 100
21 1 100 100 100
23 1 100 100 100
24 1 100 100 100
25 1 100 100 100
27 1 100 100 100
30 1 100 100 100
31 1 100 100 100
32 1 100 100 100
33 1 100 100 100
34 1 100 100 100
35 1 100 100 100
38 1 100 100 100
40 1 100 100 100
41 1 500 500 500
43 1 500 500 500
44 1 500 500 500
46 1 500 500 500
47 1 500 500 500
如果您更喜欢基于 FS + OFS
的方法,那么
mawk 'NF *= (OFS = (_=+)<11||(40<_) ? FS : __)^!__' FS='500' __='100'