ruby delete hidden characters from entire file - ruby

I have text file which contains the below hidden characters which I got with sed.
\033[H\033[2J\033
When I open file with vi and seeing the above code as below,
^[[H^[[2J^[[H^[[2J
Due to this hidden characters am facing some issue while processing file. Is there any to get rid of this hidden characters in entire file before processing it.

If the file size is not too big, you can read the whole file contents in, and then remove all the escaped sequences.
content = File.read('your_input_file_path')
content.gsub!(/\033\[(?:H|2J)/, '')
content.split(/\r?\n/).each do |line|
# process line
end
You can generalize the Regex used according to the escaped sequence pattern. In you example, it seems it's \033[ followed by an optional digit, and then a letter. Which can be updated as:
content.gsub!(/\033\[\d?[A-Z]/, '')

One way to remove non-printing characters with ASCII values less than 32 (" ".ord #=> 32) follows.
def remove_invisible(infile, outfile)
File.write(outfile,
File.read(infile).
codepoints.
reject { |n| n < 32 }.
map(&:chr).
join
)
Suppose File.read(infile) returns
str = "\033[H\033[2J\033"
#=> "\e[H\e[2J\e"
then
a = str.codepoints
#=> [27, 91, 72, 27, 91, 50, 74, 27]
b = a.reject { |n| n < 32 }
#=> [91, 72, 91, 50, 74]
c = b.map(&:chr)
#=> ["[", "H", "[", "2", "J"]
c.join
#=> "[H[2J"

Related

Can't encipher text in Ruby. It showes me the last letter of cipher-key in all my plaintext after iterating

Can't encipher text in Ruby. It showes me the last letter of cipher-key in all my plaintext after iterating.
key is: VCHPRZGJNTLSKFBDQWAXEUYMOI
plaintext is: Hello, CS-50!
expected ciphered_text: Jrssb, HA-50!
I got ciphered_text: Iiiii, II-50!
I don't know why I got a last letter of a key (I) in every char of ciphered_text....
Maybe I need a "break" after every succes "if". But it doesn't helped.
Here is my code:
# Design and implement a program, substitution, that encrypts messages using a substitution cipher.
plaintext_str = 'Hello, CS-50!'
key_str = 'VCHPRZGJNTLSKFBDQWAXEUYMOI'
# Converting string into array:
plaintext = plaintext_str.split('')
key = key_str.split('')
# Check if letter is alphabetical
def alpha?(char)
char.match?(/^[[:alpha:]]$/)
end
# Check if letter is in uppercase
def upper?(char)
char.match?(/^[[:upper:]]$/)
end
# # Check if letter is in lowercase
def lower?(char)
char.match?(/^[[:lower:]]$/)
end
# ASCII arrays value assigned to capital letters for alphabets
capital_letters = [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90]
# ASCII arrays value assigned to small letters for alphabets
small_letters = [97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122]
# Define variable for ciphertext:
ciphertext = ''
# iterating each plaintext's char (i-th):
plaintext.each_index do |i|
# iterating each key's char j-th on i-th char of plaintext:
key.each_index do |j|
# If char in plaintext is alphabetical:
if alpha?(plaintext[i])
# Check if letter is in uppercase
if upper?(plaintext[i])
capital_letters.each_index do |k|
# Checking if plaintext's letter is equal to alphabet's letter in [j]
if plaintext[i].ord == capital_letters[k]
ciphertext[i] = key[j].upcase
break
end
end
# Check if letter is in lowercase
elsif lower?(plaintext[i])
small_letters.each_index do |l|
if plaintext[i].ord == small_letters[l]
ciphertext[i] = key[j].downcase
break
end
end
end
# if non-alphabetical:
else
ciphertext[i] = plaintext[i]
end
end
end
puts "ciphertext: #{ciphertext}"
As a preface, the code you have here looks an awful lot like C. There are a lot of concepts that Ruby provides which can make problems like this into significantly shorter solutions. For now, we'll focus on what's wrong with your code as it is.
The main issue is you have three index variables, i from plaintext, j from key, and k from capital_letters. You check that if plaintext[i] == capital_letters[k], then you place key[j] at the ith position. But, since j was never participating in the checks, you will simply pass this check for all indices in your key variable. So, you might as well have ciphertext[i] = key.last.upcase, and if you check key, the last entry is I, hence why your output is nothing but I's.
Some suggestions for how you could simplify your code:
def encipher(plaintext, key)
# Make a table that maps { plaintext character => target character }
# With your input example, table = {"A" => "V", "B" => "C", "C" => "H", ... }
table = key.chars
.each_with_index
.map { |sub, index| [Array("A".."Z")[index], sub] }
.to_h
plaintext.map { |char|
# TODO: Using char and table, encipher exactly one character
}.join
end

counting length of number and character inside string using regex in ruby

how to counting length of number and character inside string using regex in ruby?
if i have some case like this, how to resolve it?
example :
abc = "12345678a"
after counting using regex, i want get result like this :
number = 8
char = 1
how to do that?
Try following
abc = "12345678a"
abc.scan(/\d/).length
# => 8
abc.scan(/\D/).length
# => 1
No regex:
abc = "12345678a"
p abc.count("0-9") # => 8
p abc.count("a-zA-Z") # => 1
This is an optional, but I still think regex is better.
irb(main):051:0> number, char = abc.bytes.to_a.partition { |e| e >= 48 and e <= 57}
=> [[49, 50, 51, 52, 53, 54, 55, 56], [97]]
irb(main):053:0> number.count
=> 8
irb(main):054:0> char.count
=> 1
partition: Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.

How to analyze the "max" method

Can someone explain why "time" is the max value here?
my_array = %w{hello my time here is long}
my_array.max #=> "time"
Because alphabetically t in time is greater here among others in your array my_array.
Here is one way,how string comparisons happened :
'hello' > 'time' # => false
'my' > 'time' # => false
'here' > 'time' # => false
'is' > 'time' # => false
'long' > 'time' # => false
To understand the outputs of the above fragment code,you must need to see String#<=> documentation. As your my_array contains all string instances,which has called the method <=>,to build the output of max.
Documentations says Enumerable#max:
Enumerable#max,without block assumes all objects implement Comparable.
Here's how computers look at the strings and compare them.
If we look at the first characters of each word it'll help a little, because we know how the alphabet orders letters:
%w[hello my time here is long].map{ |s| s[0] }.sort # => ["h", "h", "i", "l", "m", "t"]
But that doesn't really help visualize it, so here's a look at each word's letters as a computer sees them:
%w[time tome].each do |w|
puts w.chars.map(&:ord).join(', ')
end
# >> 116, 105, 109, 101
# >> 116, 111, 109, 101
Each letter has a value. Over the years there have been many different ways of ordering letters for a computer, which caused the character to value mapping to change. EBCDIC and ASCII have been the most popular but have different orders. We're usually dealing with ASCII, or a derivative, which is set by the OS.
Look at how the characters in the words are represented by the values in the following output. It should make it easy to understand what the computer is doing then.
%w[he hello help holler hollow].sort.each do |w|
puts '"%6s": %s' % [ w, w.chars.map(&:ord).join(', ') ]
end
# >> " he": 104, 101
# >> " hello": 104, 101, 108, 108, 111
# >> " help": 104, 101, 108, 112
# >> "holler": 104, 111, 108, 108, 101, 114
# >> "hollow": 104, 111, 108, 108, 111, 119

Ruby Byte XOR strange result - help please

I was doing some XOR of data and things were going well with my hex based XOR. It was recommend that I use a byte XOR (^) and only work with bytes. I thought that will take no time to change that but I have the some strange behaviour that I had not expected.
Could some add a little light as to why I'm getting a different result if I'm processing the string as bytes. I was expecting it to be the same.
m_hex_string ="124f33e6a118566377f237075354541f0a5a1b"
m_XOR_string ="662756c6c27732065796586974207468652870"
m_expected ="the code don't work"
m_expected_hex ="74686520636f646520646f6e277420776f726b"
def XOR_hex_strings(a,b)
(a.hex ^ b.hex).to_s(16)
end
def XOR_byte_strings(s1,s2)
xored = s1.bytes.zip(s2.bytes).map { |(a,b)| a ^ b }.pack('c*')
end
def hex_digest(hexdigest)
[hexdigest].pack("H*")
end
puts "My strings for stack overflow"
puts "'"+hex_digest(XOR_hex_strings(m_hex_string,m_XOR_string))+"'"
puts "'"+hex_digest(XOR_byte_strings(m_hex_string,m_XOR_string))+"'"
Results:
My strings for stack overflow
'the code don't work'
'tje`#ode ?on't ~mrk'
The text should be the same 'the code don't work' for both methods. I'd really like to know why rather than just a correct code fragment. thanks.
As already said in the comments, bytes doesn't take the hex format into account, it just returns the integer values for "1", "2", "4", "f" etc. You can convert the hex string with pack:
[m_hex_string].pack("H*")
# => "\x12O3\xE6\xA1\x18Vcw\xF27\aSTT\x1F\nZ\e"
unpack converts this into a byte array, just like bytes but more explicit and faster (IIRC):
[m_hex_string].pack("H*").unpack("C*")
# => [18, 79, 51, 230, 161, 24, 86, 99, 119, 242, 55, 7, 83, 84, 84, 31, 10, 90, 27]
The final method would look like:
def XOR_pack_unpack_strings(s1, s2)
s1_bytes = [s1].pack("H*").unpack("C*")
s2_bytes = [s2].pack("H*").unpack("C*")
s1_bytes.zip(s2_bytes).map { |a, b| a ^ b }.pack('C*')
end
If speed is an issue, take a look at the fast_xor gem:
require 'xor'
def XOR_fast_xor_strings(s1_hex, s2_hex)
s1 = [s1_hex].pack("H*")
s2 = [s2_hex].pack("H*")
s1.xor!(s2)
end

Remove "\n\" from string

Is there any way to remove "\r\" from string?
Sofar i manage to remove only "\r" with mystring.gsub(/\r/,"")
How do I remove all 3 characters \r\ ?
In your string, do you have the literal characters "\" and "r", or do you have the escape sequence "\r"?
If you have the string foo\r\fbar, then your string is 8 characters long:
"foo\r\fbar".split(//).map(&:ord)
=> [102, 111, 111, 13, 12, 98, 97, 114]
What you want to remove are the \r and \f characters, or character codes 13 and 12. You can't remove just the leading slash in the \f, because \f is just one character. If this is your case, you can use:
"foo\r\fbar".gsub(/\r\f/, "")
=> "foobar"
However, if you have the literal sequence foo\\r\\fbar:
"foo\\r\\fbar".split(//).map(&:ord)
=> [102, 111, 111, 92, 114, 92, 102, 98, 97, 114]
Then you can remove the \r and the slash before the "f":
"foo\\r\\fbar".gsub(/\\r\\/, "")
=> "foofbar"
If you have the sequence foo\r\\fbar:
"foo\r\\fbar".split(//).map(&:ord)
=> [102, 111, 111, 13, 92, 102, 98, 97, 114]
Then you can likewise remove the \r and the slash before the "f":
"foo\r\\fbar".gsub(/\r\\/, "")
=> "foofbar"
Use this:
mystring.gsub(/\r\\/,"")
mystring.gsub(/\\r\\/,"")
Ivaylo was so close :P
I tested it on http://rubular.com/
As you can tell, it's difficult for us to figure out what characters you actually need to remove, because you are contradicting yourself. In the title you say "\n\" and in the question you say "\r\". Either way, here's what I'd do in order to find out exactly what I need to search for.
Starting with the string in question:
mystring = "\n\\"
I'd use the bytes method to have Ruby show me what I should use:
mystring = "\n\\" # => "\n\\"
mystring.bytes.map{ |b| '%02x' % b } # => ["0a", "5c"]
mystring.tr("\x0a\x5c", '') # => ""
mystring.gsub(/\x0a\x5c/, '') # => ""
mystring = "\r\\" # => "\r\\"
mystring.bytes.map{ |b| '%02x' % b } # => ["0d", "5c"]
mystring.tr("\x0d\x5c", '') # => ""
mystring.gsub(/\x0d\x5c/, '') # => ""
Dealing with escaped characters can be a pain in any programming language, but if I look at the exact bytes that make up the character I can't go wrong, as long as I'm dealing with ASCII. If it's another character set, I'll want to use the chars method, and adjust my pattern appropriately:
mystring = "\n\\"
mystring.chars.to_a # => ["\n", "\\"]
mystring.gsub(/\n\\/, '') # => ""
mystring.tr("\n\\", '') # => ""
mystring = "\r\\"
mystring.chars.to_a # => ["\r", "\\"]
mystring.tr("\r\\", '') # => ""
mystring.gsub(/\r\\/, '') # => ""

Resources