Shell 如何使用awk&;sed使用匹配输入编辑特定字段

Shell 如何使用awk&;sed使用匹配输入编辑特定字段,shell,awk,sed,Shell,Awk,Sed,嗨,我是一个新的使用awk,我试图编辑一个基于输入的特定字段 e、 g分隔符为: item.txt file comics:stan lee:5:1:2 comics:stan lim:1:2:3 我想使用awk显示整行&我想使用sed根据用户的输入编辑第三个字段,我应该如何从这里开始 echo: "Enter Field 1: " read field_one echo: "Enter field 2: " read field_two #need awk statement

嗨,我是一个新的使用awk,我试图编辑一个基于输入的特定字段

e、 g分隔符为:

 item.txt file
 comics:stan lee:5:1:2
 comics:stan lim:1:2:3
我想使用awk显示整行&我想使用sed根据用户的输入编辑第三个字段,我应该如何从这里开始

 echo: "Enter Field 1: "
 read field_one
 echo: "Enter field 2: "
 read field_two
 #need awk statement
 echo "Enter New Field 3: "
 read field_three_new
 sed -i "/^$field_one:$field_two:/ s/$field_three_new/$field_three/" item.txt || tee item.txt

不要使用sed编辑该行;如果用户输入sed解释为控制字符的内容(例如
/
{
}
\
等等),那么结果会很糟糕。尝试您的脚本并为其中一个变量输入
/
,sed将抱怨语法错误

您可以使用awk执行以下两项操作:

echo "Enter Field 1: "
read field_one
echo "Enter field 2: "
read field_two

awk -F : -v f1="$field_one" -v f2="$field_two" '$1 == f1 && $2 == f2' item.txt

echo "Enter New Field 3: "
read field_three_new

# If you have GNU awk 4.1.0 or later:
awk -i inplace -F : -v f1="$field_one" -v f2="$field_two" -v f3="$field_three_new" 'BEGIN { OFS=FS } $1 == f1 && $2 == f2 { $3 = f3 } 1' item.txt

# otherwise:
# the && between the commands are to short-circuit in case of an error; if one of
# the commands fails, the others should not be executed anymore. Kudos to
# Ed Morton for catching that.
tempfile=$(mktemp) &&
awk -F : -v f1="$field_one" -v f2="$field_two" -v f3="$field_three_new" 'BEGIN { OFS=FS } $1 == f1 && $2 == f2 { $3 = f3 } 1' item.txt > "$tempfile" &&
mv "$tempfile" item.txt

# or, keeping a backup (this is my preferred method)
cp item.txt item.txt~ &&
awk -F : -v f1="$field_one" -v f2="$field_two" -v f3="$field_three_new" 'BEGIN { OFS=FS } $1 == f1 && $2 == f2 { $3 = f3 } 1' item.txt~ > item.txt
其优点是,在不进行代码解释的上下文中,awk变量被设置为shell变量,因此可以优雅地处理特殊字符

awk代码相当简单。命令行选项
-F:
将字段分隔符设置为
,因此
$1
将是第一个冒号分隔的字段(例如
漫画
),
$2
第二个字段(例如
stan lee
)等等
-v varname=value
将名为
varname
的awk变量设置为值
value
;以后可以在脚本中使用该变量

在第一次通话中

$1 == f1 && $2 == f2
选择其中字段1等于
f1
(设置为shell脚本中的第一个用户输入),字段2设置为
f2
(设置为第二个)的行

在第二次通话中

BEGIN {                # once right at the start (before the first line)
  OFS = FS             # set the output field separator to the field separator.
}                      # Now both are :
$1 == f1 && $2 == f2 { # if the current line matches the condition from before
  $3 = f3              # replace the third field with the third user input
}
1                      # then select all lines for printing. This works because
                       # by convention, 1 means true (as do all non-zero values)

OFS=FS的
OFS
功能是必需的,因为如果字段发生更改,默认的打印操作将逐个打印字段,并在字段之间放置输出字段分隔符。这与未更改的行无关,这些行是逐字重复的。

您好,我收到一个错误,说not an option:-i运行此命令时,
-i inplace
需要GNU awk 4.1.0或更高版本。如果没有,请将输出从awk重定向到一个临时文件,然后将其移回原始名称。因此它应该是awk>temp.txt?在中编辑。不过,说真的,我的建议是,从一开始就阅读shell教程。看起来你缺乏对非常基本的机制的理解,堆栈溢出驱动的开发不是一个合理的模型;mv-tmp文件,始终执行
cmd-file>tmp&&mv-tmp-file
,这样,如果
cmd
失败,您就不会删除原始文件。e、 g.想象一下,如果
cp item.txt item.txt~
失败,在最后一个示例中,
item.txt
会发生什么。顺便说一句,您应该设置IFS=并在read中使用-r。