我正在尝试使用Bourne Shell中的sed
命令更新特定行上的特定字段。
让我们说我有一个文件TopScorer.txt
Player:Games:Goals:Assists
Salah:9:9:3
Kane:10:8:4
我需要更新玩家的第三列(目标),我尝试了此命令,除非“游戏”和“目标”具有相同的值,然后它更新了第一个命令,否则该命令才起作用
player="Salah"
NewGoals="10"
OldGoals=$(awk -F':' '$1=="'$player'"' TopScorer.txt | cut -d':' -f3)
sed -i '/^'$player'/ s/'$OldGoals'/'$NewGoals'/' TopScorer.txt
Output> Salah:10:9:3 instead of Salah:9:10:3
有什么解决办法吗?我应该使用定界符和$3==...
来指定该字段吗?
我还尝试了第二次出现的选项/ 2,但对我来说这不是很方便。
答案 0 :(得分:4)
您只能单独使用awk
而不是sed
进行此操作。另请注意,awk
具有内部语法,可从shell导入变量。所以您的代码就变成了
awk -F: -v pl="$player" -v goals="$NewGoals"
'BEGIN { OFS = FS } $1 == pl { $3= goals }1' TopScorer.txt
-F:
将输入定界符设置为:
,涉及-v
的部分将您的shell变量导入到awk
的上下文中。 BEGIN { OFS = FS }
将输出字段分隔符设置为与输入相同。然后,我们使用导入的变量进行匹配,并将$3
更新为所需值。
要就地进行修改,请使用一个临时文件
awk -F: -v pl="$player" -v goals="$NewGoals"
'BEGIN { OFS = FS } $1 == pl { $3= goals }1' TopScorer.txt > tmpfile && mv tmpfile TopScorer.txt
答案 1 :(得分:2)
您可以使用Perl尝试
Param([string]$user="")
Get-ADUser -Filter {mail -like "$user"} |
Unlock-ADAccount -PassThru |
Sync-ADObject -Destination "AZUDCMO01"
或导出它们并在单引号内调用Perl一线工具
$ player="Salah"
$ NewGoals="10"
$ perl -F: -lane "\$F[2]=$NewGoals if ( \$F[0] eq $player ) ; print join(':',@F) " TopScorer.txt
Player:Games:Goals:Assists
Salah:9:10:3
Kane:10:8:4
$
请注意,Perl具有-i开关,您可以就地进行替换,因此
$ export NewGoals="10"
$ export player="Salah"
$ perl -F: -lane '$F[2]=$ENV{NewGoals} if $F[0] eq $ENV{player} ; print join(":",@F) ' TopScorer.txt
Player:Games:Goals:Assists
Salah:9:10:3
Kane:10:8:4
$
答案 2 :(得分:2)
这可能对您有用(GNU sed):
(player=Salah;newGoals=10;sed -i "/^$name/s/[^:]*/$newGoals/3" /tmp/file)
使用子外壳程序,以免污染当前的外壳程序(...)
。使用sed和模式匹配将每个记录的第一字段与变量player
匹配,并将匹配记录的第三字段替换为newGoals
的内容。
P.S。如果在后续处理中需要变量,则不需要子外壳,即删除(
和)
答案 3 :(得分:1)
这将起作用。
在sed的第一部分中,我尝试匹配用于对播放器进行数学运算的整行,并且使用 \(。
来保留要保留的所有字段。第二部分,我用一些常量以及 \ 1 的值和 \ 2
的值重建行player="Salah"
NewGoals="10"
sed "s/^$player:\([^:]*\):[^:]*:\([^:]*\)\$/$player:\1:$NewGoals:\2/"
答案 4 :(得分:1)
能否请您尝试一次。这种方法的优势在于,我不是对目标进行硬编码的领域。该程序将在目标存在的任何位置(例如->第4或第5个字段)查找标题的字段,它将仅针对该特定列进行更改。
第一个解决方案: :当您需要更改所有出现的玩家姓名时,请使用以下命令。
NewGoals=10
awk -v newgoals="$NewGoals" 'BEGIN{FS=OFS=":"} FNR==1{for(i=1;i<=NF;i++){if($i=="Goals"){field=i}}} FNR>1{if($1=="Salah"){$field=newgoals}} 1' Input_file
第二个解决方案: :如果您只想将特定玩家的目标值更改为特定行,请尝试执行以下操作。
NewGoals=10
awk -v newgoals="$NewGoals" 'BEGIN{FS=OFS=":"} FNR==1{for(i=1;i<=NF;i++){if($i=="Goals"){field=i}}} FNR>1{if($1=="Salah" && FNR==2){$field=newgoals}} 1' Input_file
以上仅对第2行进行更改,您可以通过在第二种情况下更改FNR==2
来进行更改,其中FNR引用awk
中的行号。如果要将输出保存到Input_file本身,则可以在上述代码后附加> temp_file && mv temp_file Input_file
。