このサイトで同様の投稿を見ましたが、問題を解決できませんでした。
1行に1つずつ8桁のID番号を含む入力ファイル(ids.txt)があります。このような:
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
username_prefixフィールドのIDと一致するCSVファイルのすべての行が新しいファイルに移動されるように、IDファイルをsedコマンド(または他のコマンド)への入力として使用したいと思います。したがって、このプロセスの期待される出力は、次の生の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