append_to_text_file.sf 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Append_a_record_to_the_end_of_a_text_file
  4. #
  5. define (
  6. RECORD_FIELDS = %w(account password UID GID GECOS directory shell),
  7. GECOS_FIELDS = %w(fullname office extension homephone email),
  8. RECORD_SEP = ':',
  9. GECOS_SEP = ',',
  10. PASSWD_FILE = (Dir.tmp + 'passwd.txt'),
  11. )
  12. # here's our three records
  13. var records_to_write = [
  14. Hash(
  15. account => 'jsmith',
  16. password => 'x',
  17. UID => 1001,
  18. GID => 1000,
  19. GECOS => Hash(
  20. fullname => 'John Smith',
  21. office => 'Room 1007',
  22. extension => '(234)555-8917',
  23. homephone => '(234)555-0077',
  24. email => 'jsmith@rosettacode.org',
  25. ),
  26. directory => '/home/jsmith',
  27. shell => '/bin/bash',
  28. ),
  29. Hash(
  30. account => 'jdoe',
  31. password => 'x',
  32. UID => 1002,
  33. GID => 1000,
  34. GECOS => Hash(
  35. fullname => 'Jane Doe',
  36. office => 'Room 1004',
  37. extension => '(234)555-8914',
  38. homephone => '(234)555-0044',
  39. email => 'jdoe@rosettacode.org',
  40. ),
  41. directory => '/home/jdoe',
  42. shell => '/bin/bash',
  43. ),
  44. ];
  45. var record_to_append = Hash(
  46. account => 'xyz',
  47. password => 'x',
  48. UID => 1003,
  49. GID => 1000,
  50. GECOS => Hash(
  51. fullname => 'X Yz',
  52. office => 'Room 1003',
  53. extension => '(234)555-8913',
  54. homephone => '(234)555-0033',
  55. email => 'xyz@rosettacode.org',
  56. ),
  57. directory => '/home/xyz',
  58. shell => '/bin/bash',
  59. );
  60. func record_to_string(rec, sep = RECORD_SEP, fields = RECORD_FIELDS) {
  61. gather {
  62. fields.each { |field|
  63. var r = rec{field} \\ die "Field #{field} not found"
  64. take(field == 'GECOS' ? record_to_string(r, GECOS_SEP, GECOS_FIELDS)
  65. : r)
  66. }
  67. }.join(sep)
  68. }
  69. func write_records_to_file(records, filename = PASSWD_FILE, append = false) {
  70. File(filename).(append ? :open_a : :open_w)(\var fh, \var err)
  71. err && die "Can't open #{filename}: #{err}";
  72. fh.flock(File.LOCK_EX) || die "Can't lock #{filename}: $!"
  73. fh.seek(0, File.SEEK_END) || die "Can't seek #{filename}: $!"
  74. records.each { |record| fh.say(record_to_string(record)) }
  75. fh.flock(File.LOCK_UN) || die "Can't unlock #{filename}: $!"
  76. fh.close
  77. }
  78. # write two records to file
  79. write_records_to_file(records: records_to_write);
  80. # append one more record to file
  81. write_records_to_file(records: [record_to_append], append: true);
  82. # test
  83. File(PASSWD_FILE).open_r(\var fh, \var err)
  84. err && die "Can't open file #{PASSWD_FILE}: #{err}"
  85. var lines = fh.lines
  86. # There should be more than one line
  87. assert(lines.len > 1)
  88. # Check the last line
  89. assert_eq(lines[-1], 'xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,' +
  90. '(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/bash')
  91. say "** Test passed!"