我看过这个网站上的类似帖子,但无法让它们解决我的问题。
我有一个输入文件 (ids.txt),其中包含 8 位 ID 号,每行 1 个。像这样的东西:
11111111
22222222
然后我有一个 CSV 文件 (users.csv),如下所示:
username_prefix user_type expiry_date comments
11111111 SomeTypeHere 31/12/2017 EDT0029448
22222222 SomeTypeHere 31/12/2017 EDT0029448
33333333 SomeTypeHere 31/12/2017 EDT0029448
44444444 SomeTypeHere 31/12/2017 EDT0029448
55555555 SomeTypeHere 31/12/2017 EDT0029448
我想使用 ID 文件作为 sed 命令(或其他命令)的输入,以便 CSV 文件中与 username_prefix 字段与 ID 匹配的任何行都会移动到新文件中。因此,此过程的预期输出是原始 CSV 文件如下所示:
username_prefix user_type expiry_date comments
33333333 SomeTypeHere 31/12/2017 EDT0029448
44444444 SomeTypeHere 31/12/2017 EDT0029448
55555555 SomeTypeHere 31/12/2017 EDT0029448
并且将出现一个新的 CSV 文件,其中包含已删除的行,例如:
username_prefix user_type expiry_date comments
11111111 SomeTypeHere 31/12/2017 EDT0029448
22222222 SomeTypeHere 31/12/2017 EDT0029448
我尝试了以下命令,但它生成了 0 字节的输出文件。
cat ids.txt | sed "/$/d" ./adhocUsers_upload_EDT0029448.csv > removed.csv
顺便说一句,解决方案不必使用sed
.从我在谷歌上搜索到的内容来看,它似乎是合适的工具。
答案1
听起来命令很简单awk
:
awk -F, 'NR==FNR{IDs[$0]++;next}
{ print >(($1 in IDs)?"removed.csv":"Updated.csv")}
' IDs.txt Users.csv
答案2
这是一个红宝石解决方案。它有点长,但当 ID 的顺序与用户文件不同时它也可以工作。 (而且它比 sed 更易于维护)
#!/usr/bin/env ruby
ids = []
users = {}
header = ""
# Read the contents of the user-file into a Hash
File.open('users.csv','r') do |users_file|
header = users_file.gets
users_file.each do |line|
id, *content = line.chomp.split(',')
users[id] = content
end
end
# For each line in the id-file, add an appropriate line to the removed-file.
File.open('ids.txt','r') do |ids_file|
File.open('removed.csv', 'a') do |removed_file|
removed_file.puts header
ids_file.each do |line|
id = line.chomp
if users[id]
removed_file.puts "#{id},#{users[id].join(',')}"
users.delete id
end
end
end
end
# Finally fill the original file with what's left
File.open('original.csv', 'a') do |original_file|
original_file.puts header
users.each_pair do |id, line|
original_file.puts "#{id},#{line.join(',')}"
end
end
您的输出将位于文件“original.csv”和“removed.csv”中。如果这不是您预想的位置,只需移动文件即可;)
答案3
尝试使用此脚本,它将保存匹配的行removed.csv
,其他所有内容都将发送到标准输出。请注意,该username_prefix user_type expiry_date comments
行不会发送到removed.csv
文件,因此您必须手动添加它。
#!/usr/bin/env bash
id_file=${1}
csv_file=${2}
removed_file=${3}
while read -r user; do
matched=''
while read -r id; do
if <<< "${user}" grep -F -e "${id}" > '/dev/null'; then
matched='yes'
break
else
matched='no'
fi
done < "${id_file}"
[[ "${matched}" == 'yes' ]] && echo "${user}" >> "${removed_file}"
[[ "${matched}" == 'no' ]] && echo "${user}"
done < "${csv_file}"
例子:
$ myscript.sh ids.txt users.csv removed.csv
username_prefix user_type expiry_date comments
33333333 SomeTypeHere 31/12/2017 EDT0029448
44444444 SomeTypeHere 31/12/2017 EDT0029448
55555555 SomeTypeHere 31/12/2017 EDT0029448
$ cat removed.csv
11111111 SomeTypeHere 31/12/2017 EDT0029448
22222222 SomeTypeHere 31/12/2017 EDT0029448