【问题标题】:shell / bash script - Add value to a single filtered row in csv - awk / sedshell / bash 脚本 - 将值添加到 csv 中的单个过滤行 - awk / sed
【发布时间】:2022-01-25 23:03:32
【问题描述】:

对不起我的英语。我正在为新员工的入职流程编写一个脚本,例如“零接触”,并且我在使用 shell bash 脚本操作 csv 时遇到了一些问题。

我的输入 csv 样本 tmp.csv

SN,HOSTNAME,OWNER,MODEL,USER
C02G1,,aaa@aaa.la,MacBook Pro,
C02G71X,HOSTNAME0001,bbbb@bbb.com,MacBook Pro,
FVFGH0S,,cccc@cccc.com,MacBook Pro,
PC24Q,,ddd@ddd.com,Macbook Air,

所需的输出(可以是新文件或编辑输入文件):

SN,HOSTNAME,OWNER,MODEL,USER
C02G1,,aaa@aaa.la,MacBook Pro,
C02G71X,HOSTNAME0001,bbbb@bbb.com,MacBook Pro,username
FVFGH0S,,cccc@cccc.com,MacBook Pro,
PC24Q,,ddd@ddd.com,Macbook Air,

我的脚本:

#!/bin/sh
# Get the current device's serial number
SERIAL=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')
# File name
tmpFile=$'tmp.csv'

# Download the CSV from Google Drive, file must be set to Shared With Anyone with Link (or Shared with Anyone)
curl -L -o $tmpFile 'https://docs.google.com/spreadsheets/d/XXXXXXXX/export?format=csv'

# Delete unwanted characters
sed -i'BAK' "s/$(printf '\r')\$//" $tmpFile

# Get username MAC
user=$(id -un)

while IFS=, read -r SN HOSTNAME OWNER MODEL USER
    do
      if [ "$SN" == "$SERIAL" ]
        then            
            hostname=$HOSTNAME
            awk -F, -v old="$USER" -v new="$user" '{gsub(old,new,$5);print $0}' $tmpFile > tmp3.csv
            fi
done < $tmpFile

sudo scutil --set HostName $hostname
sudo scutil --set LocalHostName $hostname
sudo scutil --set ComputerName $hostname
dscacheutil -flushcache

etc etc etc......

使用我的脚本输出:

SN,HOSTNAME,OWNER,MODEL,USER
C02G1,,aaa@aaa.la,MacBook Pro,username
C02G71X,HOSTNAME0001,bbbb@bbb.com,MacBook Pro,username
FVFGH0S,,cccc@cccc.com,MacBook Pro,username
PC24Q,,ddd@ddd.com,Macbook Air,username

总结: 所以我需要的是仅在与 SN 与 $SERIAL 匹配的行中将 $user 添加到 csv 的 USER 列中

在此先感谢,如果有人觉得此代码可能有帮助,我可以在完成后发送!

【问题讨论】:

  • 如果您的 USER 始终是最后一列,您可以这样做:sed /"${sn}"'/s/,[^,]*$/,'"${user}"/ tmp.csv
  • 您应该将您的脚本复制/粘贴到shellcheck.net 并修复它告诉您的问题。

标签: bash shell csv search awk


【解决方案1】:

首先,我不知道您是如何获得以, 作为分隔符的输出的。我必须明确设置它,否则awk 正在使用空间。

但回到问题,你可以使用两条规则:

  • 匹配行并更新第 5 个字段,
  • 另一个匹配所有内容并打印整行
$1 == sn { $5 = user }
{ print $0 }

在脚本中它将如下所示:

#!/usr/bin/env bash

SN_TO_MATCH="C02G71X"
USER_TO_ADD="foobar"

awk -F, -v OFS=, -v sn="${SN_TO_MATCH}" -v user="${USER_TO_ADD}" '$1==sn {$5=user} {print $0}' tmp.csv

输出:

SN,HOSTNAME,OWNER,MODEL,USER
C02G1,,aaa@aaa.la,MacBook Pro,
C02G71X,HOSTNAME0001,bbbb@bbb.com,MacBook Pro,foobar
FVFGH0S,,cccc@cccc.com,MacBook Pro,
PC24Q,,ddd@ddd.com,Macbook Air,

【讨论】:

【解决方案2】:

这不是 awk,但它可能对您有用。我正在使用Miller

这是一个简化的例子

#!/bin/bash

serial="C02G71X"
user="tom"

mlr --csv put 'if($SN=="'"$serial"'"){$USER="'"$user"'"} then {$USER=""}' input.csv >output.csv
+---------+--------------+---------------+-------------+------+
| SN      | HOSTNAME     | OWNER         | MODEL       | USER |
+---------+--------------+---------------+-------------+------+
| C02G1   |              | aaa@aaa.la    | MacBook Pro |      |
| C02G71X | HOSTNAME0001 | bbbb@bbb.com  | MacBook Pro | tom  |
| FVFGH0S |              | cccc@cccc.com | MacBook Pro |      |
| PC24Q   |              | ddd@ddd.com   | Macbook Air |      |
+---------+--------------+---------------+-------------+------+

给你的

【讨论】:

    猜你喜欢
    • 2013-08-17
    • 2012-03-19
    • 2022-01-20
    • 2010-11-29
    • 1970-01-01
    • 2013-06-15
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多