making a loop show as a counter in csh - loops

Im currently working on a code in csh and when it gets to the loop for example it goes
loop end count=1
loop end count=2
loop end count=3
loop end count=4
loop end count=5 etc etc
Is there a way I can make it just say
loop end count=(number just counts up here without adding lines)
so I don't keep getting a wall of text when I run the code?
Thanks

if you are on a vt100 compatible terminal (most all linux terminals) you can generate appropriate terminal control codes:
echo -n "count is:"
echo -n "^[7" # save cursor position
set i = 0
while ( 1 )
# i = $i + 1
echo -n "^[[u^[[K" #move back to saved position and erase end of line
echo -n "i=" , $i
sleep 1
end
Note "^[" is the ASCII escape character, not caret-bracket. How you get that
in a script will depend on your editor.

Related

Getting a Windows command prompt contents to a text file

I want to write a batch utility to copy the output of a command prompt window to a file. I run my command prompt windows with the maximum depth of 9999 lines, and occasionally I want to grab the output of a command whose output is off-screen. I can do this manually with the keys Ctrl-A, Ctrl-Cand then pasting the result into Notepad - I just want to automate it in a batch file with a call to:
SaveScreen <text file name>
I know I can do it with redirection, but that would involve knowing that I will need to save the output of a batch command sequence beforehand.
So if I had a batch script:
call BuildPhase1.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
call BuildPhase2.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
call BuildPhase3.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
I could write:
cls
call BuildPhase1.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase1.err & goto :ErrorExit
call BuildPhase2.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase2.err & goto :ErrorExit
call BuildPhase3.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase3.err & goto :ErrorExit
or I could just type SaveScreen batch.log when I see that a run has failed.
My experiments have got me this far:
<!-- : Begin batch script
#cscript //nologo "%~f0?.wsf" //job:JS
#exit /b
----- Begin wsf script --->
<package>
<job id="JS">
<script language="JScript">
var oShell = WScript.CreateObject("WScript.Shell");
oShell.SendKeys ("hi folks{Enter}") ;
oShell.SendKeys ("^A") ; // Ctrl-A (select all)
oShell.SendKeys ("^C") ; // Ctrl-C (copy)
oShell.SendKeys ("% ES") ; // Alt-space, E, S (select all via menu)
oShell.SendKeys ("% EY") ; // Alt-space, E, Y (copy via menu)
// ... invoke a notepad session, paste the clipboard into it, save to a file
WScript.Quit () ;
</script>
</job>
</package>
My keystrokes are making it to the command prompt so presumably I have the correct window focused - it just seems to be ignoring the Ctrl and Alt modifiers. It also recognises Ctrl-C but not Ctrl-A. Because it has ignored the Ctrl-A to select all the text, the Ctrl-C causes the batch file to think it has seen a break command.
I've seen the other answers like this one but they all deal with methods using redirection, rather than a way of doing it after the fact "on demand".
* UPDATE *
On the basis of #dxiv's pointer, here is a batch wrapper for the routine:
Get-ConsoleAsText.bat
:: save the contents of the screen console buffer to a disk file.
#set "_Filename=%~1"
#if "%_Filename%" equ "" #set "_Filename=Console.txt"
#powershell Get-ConsoleAsText.ps1 >"%_Filename%"
#exit /b 0
The Powershell routine is pretty much as was presented in the link, except that:
I had to sanitise it to remove some of the more interesting character substitutions the select/copy/paste operation introduced.
The original saved the trailing spaces as well. Those are now trimmed.
Get-ConsoleAsText.ps1
# Get-ConsoleAsText.ps1 (based on: https://devblogs.microsoft.com/powershell/capture-console-screen/)
#
# The script captures console screen buffer up to the current cursor position and returns it in plain text format.
#
# Returns: ASCII-encoded string.
#
# Example:
#
# $textFileName = "$env:temp\ConsoleBuffer.txt"
# .\Get-ConsoleAsText | out-file $textFileName -encoding ascii
# $null = [System.Diagnostics.Process]::Start("$textFileName")
#
if ($host.Name -ne 'ConsoleHost') # Check the host name and exit if the host is not the Windows PowerShell console host.
{
write-host -ForegroundColor Red "This script runs only in the console host. You cannot run this script in $($host.Name)."
exit -1
}
$textBuilder = new-object system.text.stringbuilder # Initialize string builder.
$bufferWidth = $host.ui.rawui.BufferSize.Width # Grab the console screen buffer contents using the Host console API.
$bufferHeight = $host.ui.rawui.CursorPosition.Y
$rec = new-object System.Management.Automation.Host.Rectangle 0,0,($bufferWidth - 1),$bufferHeight
$buffer = $host.ui.rawui.GetBufferContents($rec)
for($i = 0; $i -lt $bufferHeight; $i++) # Iterate through the lines in the console buffer.
{
$Line = ""
for($j = 0; $j -lt $bufferWidth; $j++)
{
$cell = $buffer[$i,$j]
$line = $line + $cell.Character
}
$line = $line.trimend(" ") # remove trailing spaces.
$null = $textBuilder.Append($line)
$null = $textBuilder.Append("`r`n")
}
return $textBuilder.ToString()
The contents of the console buffer can be retrieved with the PS script from PowerShell's team blog Capture console screen mentioned in a comment, now edited into OP's question.
The last line could also be changed to copy the contents to the clipboard instead of returning it.
Set-Clipboard -Value $textBuilder.ToString()
As a side note, the reasons for using a StringBuilder rather than direct concatenation are discussed in How does StringBuilder work internally in C# and How the StringBuilder class is implemented.

BASH scripting: Organizing output of a nested loop into a table

I have wasted so much of my time with this, I hope someone can help me. I am editing a script that is used to send values to an executable and then scrubs the output from the executable for tabulation. I have created two arrays that are filled with user inputted ranges, these ranges are then used to create a nested loop that I have put into a function (since I need to create 4 files from the output depending on another value). I admit that my code is abysmal, but it does the primary thing and that is obtaining the data I need and puts into the correct file. All I am trying to do is to get it to actually make a table with row and column labels, I just can't understand why this is so difficult.
This is the problematic area:
# Function to loop user inputted ranges in order to generate report data.
function repeat()
{
printf "%22s" 'density (10^18 m^-3)'
for a in "${density_array[#]}" # for loop to list density values in the range set by the user.
do
printf "%13s" "$a"
done
echo -e "\n" 'speed (m/s)'
#printf "%s\n" "${speed_array[#]}"
for i in "${speed_array[#]}"
do
echo "$i"
for j in "${density_array[#]}"
do
echo $j > SCATINPUT # generates a temporary file named SCATINPUT, with density value as first line.
echo $temp >> SCATINPUT # appends a new line with temperature value to SCATINPUT file.
echo $i >> SCATINPUT # appends a new line with speed value to SCATINPUT file.
echo $1 >> SCATINPUT # appends a new line with rate type from argument to SCATINPUT file.
# pipes contents of SCATINPUT file to executable, extracts value from STDOUT to RATE variable.
RATE=`path_of_executable < SCATINPUT | awk '/0\./'`
RATEF=$(printf "%.4e" $RATE) # converts number in RATE variable to scientific notation with 4 digits after decimal and sets RATEF variable.
echo -ne "\t$RATEF"
rm -f SCATINPUT # quietly deletes SCATINPUT file.
done
done
}
I am getting this output in a file:
density (10^18 m^-3) 2.0000e+00 4.0000e+00 6.0000e+00
speed (m/s)
8.0000e+06
7.6164e+04 1.4849e+05 2.1936e+059.0000e+06
5.7701e+04 1.1249e+05 1.6619e+051.0000e+07
4.3469e+04 8.4747e+04 1.2520e+051.1000e+07
3.3078e+04 6.4488e+04 9.5269e+041.2000e+07
2.5588e+04 4.9886e+04 7.3697e+04
But it should be this:
density (10^18 m^-3) 2.0000e+00 4.0000e+00 6.0000e+00
speed (m/s)
8.0000e+06 7.6164e+04 1.4849e+05 2.1936e+05
9.0000e+06 5.7701e+04 1.1249e+05 1.6619e+05
1.0000e+07 4.3469e+04 8.4747e+04 1.2520e+05
1.1000e+07 3.3078e+04 6.4488e+04 9.5269e+04
1.2000e+07 2.5588e+04 4.9886e+04 7.3697e+04
The general idea would be to replace the echo commands with comparable printf commands with formats that match the formats used to print the first/header line ...
Start by replacing echo "$i" with printf "%22s" "$i" => this should leave the cursor on the same line as $i and lined up under the 2.0000e+00
After you finish the j loop and before getting the next i do printf "\n" => this should move the cursor to the next line and ready for the next printf "%22s" "$i".
That should get you started.
If things don't line up quite right then consider replacing the echo -ne "\tRATEF" with a printf "%#s" "$RATEF" (adjust the number # to line up output as desired).

Shell - Taking the input from the user from each line

I'm trying to take the input from the user into an array but Shell is accepting user input separated by spaced. Is there any way to accept the user input given separately in each line. My code below:
#!/bin/bash
echo "enter the servers names..."
read -a array
for i in "${array[#]}"
do
echo $i
done
exit 0
Input:
hello world
I want to the input to be taken as below (in two different lines):
hello
world
Kindly help. Thanks.
You can specify the delimiter of read to stop reading, rather than newline. (read man page)
-d delim continue until the first character of DELIM is read, rather
than newline
For example:
read -d':' -a array
If you want there is no delimiter to input, you can use a loop to read into the elements of the array, then check whether the input is null string or not.
i=0
read "array[$i]"
while [ "${array[$i]}" ];
do
let "i = i+1"
read "array[$i]"
done
So the input will be
hello
world
# > there is one more empty line
According to help read:
Reads a single line from the standard input, or from file descriptor FD...
This loop would do instead:
echo "enter the servers names..."
i=0
until false; do
read server
[ -z "$server" ] && break
let i=i+1
array[$i]="$server"
done
for i in "${array[#]}"; do
echo $i
done
exit 0
The loop will exit on an empty line or EOF (ctrl-D).
Example session terminated by empty line:
#server:/tmp$ ./test.sh
enter the servers names...
se1
se2
se3
se1
se2
se3
Example session terminated by EOF on the empty line after se2:
#server:/tmp$ ./test.sh
enter the servers names...
se1
se2
se1
se2
Please note that I check for an empty string while reading the names; but it is possible to check for empty strings (or whatever else) in any loop, for example while printing them or doing other computations.
#!/bin/bash
echo "enter the servers names..."
read -a array -d '\n'
for i in "${array[#]}"
do
echo $i
done
exit 0
or
#!/bin/bash
echo "enter the servers names..."
readarray array
for i in "${array[#]}"
do
echo $i
done
exit 0

Bash script array to csv

I want to do comma separated string from my array. In my script i collecting data to array outputArr and then i want to echo it to check it out, but now i'm stuck. I want to print it on console using:
echo ${outputArr[*]}
But i'm getting wrong output. So i'm trying to debug it and write it like this:
echo ${outputArr[0]}
echo ${outputArr[1]}
echo ${outputArr[*]}
echo "-------------"
OK here is my output:
Terminally Yours
2204
2204nally Yours
-------------
and other example:
Alfa
1491
1491
-------------
Why this is overwritten with space in the beginning? Of course my goal is (finally):
Alfa;1491
In this point:
Alfa1491
EDIT:
while read -r line
do
singleLine=$line
if [[ $singleLine =~ $regexVenueName ]]
then
singleLine=${singleLine/<span id=\"ctl00_MainContent_lbPartner\" class=\"Partner\">/}
singleLine=${singleLine/<\/span> <br \/><br \/>/}
partnerVenueNameOutput+="$singleLine"
outputArr[0]=$singleLine
fi
done < "$f"
Your array contains elements with carriage returns:
$ foo=($'\rterminally yours' $'\r2204')
$ echo "${foo[0]}"
terminally yours
$ echo "${foo[1]}"
2204
$ echo "${foo[*]}"
2204inally yours
For your code, you can add the following to remove the carriage return from the variable:
singleLine=${singleLine//$'\r'/}
To remove any trailing carriage returns from each array element, try
outputArray=( "${outputArray[#]%$'\r'}" )
However, it would probably be better to examine how outputArray is set in the first place and prevent the carriage returns from being added in the first place. If you are reading from a file that uses DOS line endings, try "cleaning" it first using dos2unix.

Updating Array Value in For Loop Bash

I'm interested in updating an array element value within a for loop, but my update definition is wrong, since the output contain [counter].
Here is the code I have:
declare -a mem_set=(0 0 0 0 0 0 0)
counter=0
for i in "${domain_path[#]}"
do
cd $i
echo "$(pwd)"
for mLine in $(grep 'default.default.minmaxmemory.main' start_params.properties)
do
echo "$mLine"
done
l_bound="Xmx"
r_bound="m"
mem_set[counter]=$(echo "$mLine" | sed -e "s/.*${l_bound}//;s/${r_bound}.*//")
echo "$mem_set[counter]"
let counter=counter+1
done
The loop and the $(echo "$mLine" | sed -e "s/.*${l_bound}//;s/${r_bound}.*//") run fine, but I can't manage to get the right output. What is my update statement is missing? The output of it is 2048[counter]. Also, instead of using another counter counter in addition to i, is it possible to use i for mem_set array as well (both arrays have the same size)?
Thank you
Since feature requests to mark a comment as an answer remain declined, I copy the above solution here.
can you change echo "$mem_set[counter]" to echo "${mem_set[counter]}" and see if that prints out the right value? – 1_CR
thank you for your suggestion. Changing the format worked, so now I get the right output. – Simply_Me
In bash, you would access a variable with $.
Try,
counter=`expr $counter + 1`
or
counter=$(( counter + 1 ))

Resources