How can I convert this VBS script to Bash? - bash

I have this code in VBS that I need to rebuild in Bash. This is a snippet of a larger script that I have to convert. Can someone please help me with this?
I have read a lot of documentation on Bash in the last two days that I have been working on the larger script but am still not sure how to go about doing this. My coworker/trainer essentially handed me this and told me to use Google to learn Bash in order to do this. I feel it's also important to note that I am not familar with VBScript either.
Function Build_Param_Array()
Set objFSO = WScript.CreateObject("Scripting.Filesystemobject")
Set ReadFile = objFSO.OpenTextFile("Param_List.txt")
While Not ReadFile.AtEndOfStream
thisline = ReadFile.ReadLine
Pcount = Pcount + 1
ReDim preserve arrParam(Pcount)
If Not Right(thisline,1) = "|" Then thisline = thisline & "|"
arrParam(Pcount) = thisline
Wend
End Function

Not a vbs guru, but winging it for a general guess, it looks like it reads Param_List.txt, makes sure each line ends with a pipe character, then pushes it onto an array (arrParam).
typeset -a arrParam # declare an array
while read l # read each line from stdin into l
do arrParam+=("${l%|}|") # push the line onto the array, assuring a |
done < Param_List.txt # put the file on the loop's stdin
$l is the line read. ${l%|} is the line read, with any pipe as the last character removed; thus "${l%|}|" explicitly removes a pipe if there was one, then adds one whether or not one was removed.

Related

Bash Script: How to read a line from a file, that was passed as an argument, and store it in a variable

I need to make a program that takes as arguments a number of files that contain lines like this: num1:num2.
I need to store the left column of numbers in one array and the right column and then do some things to them. I need some help on the first part.
The number of files passed as arguments is variable. Also I don't know the name of the files neither how many lines they have. I just know that I will get at least 1 file with 1 line.
I am trying to make a loop for each argument file and then read each file line, break down each line with some string manipulation and then store the results in the 2 arrays. However I haven't succeeded. I know that I also have other kinds of mistakes but I can fix those.
When I try to run the program using:
sh <my_program_name>.sh <argument1_filename>
I just get no results on the terminal, blank screen like it is calculating something in an endless loop.
#!/bin/bash
length=0
b=1
c=1
d=0
args=$#
j=0
temp=0
temp2=0
temp3=0
temp4=0
for temp in "$#"
do
while read line
do
stringtmp=line
tmp=`expr index "$stringtmp" :`
let tmp=tmp-1
stringtmp2='expr substr $stringtmp $1 $tmp'
lengh=`expr index "$stringtmp" \n`
let tmp=tmp+2
let lengh=lengh-1
stringtmp3='expr substr $stringtmp $tmp $lengh'
array1[$length]=stringtmp2
array2[$length]=stringtmp3
let length=length+1
done
...
done
Your while loop is waiting for input from stdin. If you want to loop through contents of temp, you could use:
while read line; do
...
done<$temp

VBScript Error 9 in AtEndOfStream Loop

I am using a script like this to loop through some data in a text file:
Do Until objFile.AtEndOfStream
'Check if it is not a blank line; otherwise skip it
If Len(Trim(objFile.ReadLine)) > 0 Then
'Some code
end if
Loop
I print out the values every time through and it gets all the way to end of the file (I can see that it prints every value) but when it reaches the end it always errors out. I used on error resume next and printed out Err.Number and I get error number 9 which is Subscript out of range.
The issue with the file I'm looping through is that the last line is blank. I know this because I've opened the file, removed the final blank line and then run the code and it works fine. This is an automated process though (the file is automatically sent to the FTP and the process runs by an automated task every day) so I can't go in and manually be getting rid of the last line every day. I included that If Len(Trim(objFile.ReadLine)) > 0 Then to take this blank line into account and it works fine on the lines with data but it still throws an error at the end of file.
I could have the loop end when it reaches a blank line but I would like to keep a condition in there in the case that a blank line shows up in the middle of the code for some reason down the line. I figure it'll be cleaner to figure out if it truly is the last line of the file and then end the loop.
Any ideas? Thanks for your help!
First of all, I'd like to ask you how you're actually processing that line you read in since you don't store it anywhere. You read it and pass it to Trim() for checking, but there's no way to get at that line afterwards.
If you have yet another ReadLine within the loop (thinking that's going to be the same line), that's going to be an issue since you might be reading the "blank" line within the if statement. It'll also mean you're throwing away every second line.
It seems to me you should be using something like:
Do Until objFile.AtEndOfStream
thisLine = objFile.ReadLine
If Len(Trim(thisLine)) > 0 Then
' Some code using thisLine, NOT another ReadLine.
End If
Loop
Another thing (once that issue is clarified), are you sure that the final line contains only spaces? I think that's all trim() gets rid of. It may be that there's other white space in there causing you problems, such as TAB, for example.
One way to find out would be to take a copy of an offending file and remove all but the last couple of lines. Then you can insert debug statements into your code to see what's happening:
Do Until objFile.AtEndOfStream
thisLine = objFile.ReadLine
trimLine = Trim(thisLine)
MsgBox ("[" & trimLine & "] " & CStr(Len(trimLine))
If Len(Trim(thisLine)) > 0 Then
MsgBox ("Processing it...")
' Some code using thisLine, NOT another ReadLine.
End If
Loop

Ruby scan/gets until EOF

I want to scan unknown number of lines till all the lines are scanned. How do I do that in ruby?
For ex:
put returns between paragraphs
for linebreak add 2 spaces at end
_italic_ or **bold**
The input is not from a 'file' but through the STDIN.
Many ways to do that in ruby.
Most usually, you're gonna wanna process one line at a time, which you can do, for example, with
while line=gets
end
or
STDIN.each_line do |line|
end
or by running ruby with the -n switch, for example, which implies one of the above loops (line is being saved into $_ in each iteration, and you can addBEGIN{}, and END{}, just like in awk—this is really good for one-liners).
I wouldn't do STDIN.read, though, as that will read the whole file into memory at once (which may be bad, if the file is really big.)
Use IO#read (without length argument, it reads until EOF)
lines = STDIN.read
or use gets with nil as argument:
lines = gets(nil)
To denote EOF, type Ctrl + D (Unix) or Ctrl + Z (Windows).

Find specific column range and line using VBSCRIPT

I have a txt file that I only need to read the first line, but only want values from column 64-70 from line 1. How do I do this in vbscript? I have looked at several ways to do this but can't get exactly what I'm looking for. Please help.
For the reading characters from the line, use Mid(source_str, 64, 6). -- 6 is the length from character 64 to 70.
As for reading the first line from the text file, you will need to set up a loop to read each line until the end of the file, parse them into an array of strings, then process only the 1st.
Or, since you only need the first line, just run fsoStream.ReadLine() once.
So in your case:
Set fso = CreateObject("Scripting.FileSystemObject")
Set file = fso.OpenTextFile("filename.txt")
'This only reads the first line of the file.
'To read any others, we would need a loop.
line = file.ReadLine()
thisStr = Mid(line,64,6)

error in shell script: unexpected end of file

The following script is showing me "unexpected end of file" error. I have no clue why am I facing this error. My all the quotes are closed properly.
#!/usr/bin/sh
insertsql(){
#sqlite3 /mnt/rd/stats_flow_db.sqlite <<EOF
echo "insert into flow values($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)"
#.quit
}
for i in {1..100}
do
src_ip = "10.1.2."+$i
echo $src_ip
src_ip_octets = ${src_ip//,/}
src_ip_int = $src_ip_octets[0]*1<<24+$src_ip_octets[1]*1<<16+$src_ip_octets[2]*1<<8+$src_ip_octets[3]
dst_ip = "10.1.1."+$i
dst_ip_octets = ${dst_ip//,/}
dst_ip_int = $dst_ip_octets[0]*1<<24+$dst_ip_octets[1]*1<<16+$dst_ip_octets[2]*1<<8+$dst_ip_octets[3]
insertsql(1, 10000, $dst_ip, 20000, $src_ip, "2012-08-02,12:30:25.0","2012-08-02,12:45:25.0",0,0,0,"flow_a010105_a010104_47173_5005_1_50183d19.rrd",0,12,$src_ip_int,$dst_ip_int,3,50000000,80000000)
done
That error is caused by <<. When encountering that, the script tries to read until it finds a line which has exactly (starting in the first column) what is found after the <<. As that is never found, the script searches to the end and then complains that the file ended unexpectedly.
That will not be your only problem, however. I see at least the following other problems:
You can only use $1 to $9 for positional parameters. If you want to go beyond that, the use of the shift command is required or, if your version of the shell supports it, use braces around the variable name; e.g. ${10}, ${11}...
Variable assignments must not have whitespace arount the equal sign
To call your insertsql you must not use ( and ); you'd define a new function that way.
The cass to your insertsql function must pass the parameters whitespace separated, not comma separated.
A couple of problems:
There should be no space between equal sign and two sides of an assignment: e.g.,: dst_ip="10.1.1.$i"
String concatenation is not done using plus sign e.g., dst_ip="10.1.1.$i"
There is no shift operator in bash, no <<: $dst_ip_octets[0]*1<<24 can be done with expr $dst_ip_octets[0] * 16777216 `
Functions are called just like shell scripts, arguments are separated by space and no parenthesis: insertsql 1 10000 ...
That is because you don't follow shell syntax.
To ser variable you are not allowed to use space around = and to concatenate two parts of string you shouldn't use +. So the string
src_ip = "10.1.2."+$i
become
src_ip="10.1.2.$i"
Why you're using the string
src_ip_octets = ${src_ip//,/}
I don't know. There is absolutely no commas in you variable. So even to delete all commas it should look like (the last / is not required in case you're just deleting symbols):
src_ip_octets=${src_ip//,}
The next string has a lot of symbols that shell intepreter at its own way and that's why you get the error about unexpected end of file (especially due to heredoc <<)
src_ip_int = $src_ip_octets[0]*1<<24+$src_ip_octets[1]*1<<16+$src_ip_octets[2]*1<<8+$src_ip_octets[3]
So I don't know what exactly did you mean, though it seems to me it should be something like
src_ip_int=$(( ${src_ip_octets%%*.}+$(echo $src_ip_octets|sed 's/[0-9]\+\.\(\[0-9]\+\)\..*/\1/')+$(echo $src_ip_octets|sed 's/\([0-9]\+\.\)\{2\}\(\[0-9]\+\)\..*/\1/')+${src_ip_octets##*.} ))
The same stuff is with the next strings.
You can't do this:
dst_ip_int = $dst_ip_octets[0]*1<<24+$dst_ip_octets[1]*1<<16+$dst_ip_octets[2]*1<<8+$dst_ip_octets[3]
The shell doesn't do math. This isn't C. If you want to do this sort of calculation, you'll need to use something like bc, dc or some other tool that can do the sort of math you're attempting here.
Most of those operators are actually shell metacharacters that mean something entirely different. For example, << is input redirection, and [ and ] are used for filename globbing.

Resources