![cat 또는 grep의 출력을 sed에 대한 입력으로 사용](https://linux55.com/image/115525/cat%20%EB%98%90%EB%8A%94%20grep%EC%9D%98%20%EC%B6%9C%EB%A0%A5%EC%9D%84%20sed%EC%97%90%20%EB%8C%80%ED%95%9C%20%EC%9E%85%EB%A0%A5%EC%9C%BC%EB%A1%9C%20%EC%82%AC%EC%9A%A9.png)
이 사이트에서 유사한 게시물을 보았지만 문제를 해결할 수 없습니다.
한 줄에 하나씩 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