Unix C Shell Scripting printf help - unix

Attempting to print out a list of values from 2 different variables that are aligned correctly.
foreach finalList ($correctList $wrongList)
printf "%20s%s\n" $finalList
end
This prints them out an they are aligned, but it's one after another. How would I have it go through each item in each list and THEN go to a new line?
I want them to eventually appear like this:
Correct Incorrect
Good1 Bad1
Good2 Bad2
Good3 Bad3
Good comes from correctList
Bad comes from wrongList
Getting rid of \n makes it Like this:
Good1 Bad1 Good2 Bad2
I just want 2 columns.

You can iterate over both lists at the same time like this:
# Get the max index of the smallest list
set maxIndex = $#correctList
if ( $#wrongList < $#correctList ) then
set maxIndex = $#wrongList
endif
set index = 1
while ($index <= $maxIndex)
printf "%-20s %s\n" "$correctList[$index]" "$wrongList[$index]"
# index++
end

try getting rid of the \n

I believe the pr(1) command with the -m option will help do what you want. Look at its man page to eliminate the header/trailer options and set the column widths.
Also, I recommend you not use the C-Shell for scripting; you'll find the sh-syntax shells (sh, bash, ksh, etc) are more consistent and much easier to debug.

Related

How can I determine why this `test` does not match for tmux's session_name?

I'm trying to give my tmux panes individual titles. Since there is nothing built into tmux to assign titles, I'm using a function that will receive various properties of the pane and then lookup the title that I want based on those properties, and echo it out.
However, the test inside the function is not working as expected. Even when the session_name "portal" is passed in, it does not match the string "portal", even though the output is always exactly "portal".
I've removed all irrelevant code from the function to show just exactly the failing match:
tmux_pane_title() {
local session_name=$1
# ...
if [[ "$session_name" = "portal" ]] && echo ".${session_name}." || echo "-${session_name}-"
# ...
}
tmux set pane-border-format "#P: `tmux_pane_title \"#{session_name}\" \"#{pane_current_command}\" \"#{pane_current_path}\"` "
It always echos out "-portal-", showing the $1 is in fact "portal", but it does not match "portal" in the test.
I have tried using sed to remove newlines, but it made no difference.
However if I hard-code "portal" into the tmux format for pane-border-format it will suddenly work, suggesting there's some weird control character hidden in the name preventing it from working when I pass in session_name
tmux set pane-border-format "#P: `tmux_pane_title \"portal\" \"#{pane_current_command}\" \"#{pane_current_path}\"` "
If that's the case, how can I find and eliminate the control character? (And why would it be there? I did not enter anything weird into my tmuxinator.yml file for the session name.)
I've already tried removing control characters like this:
local session_name=$(echo $1 | tr -d "[:cntrl:]")
If that's not the case, how can I figure out what is breaking this function?
P.S. I'm on tmux 3.1b.
This is NOT an answer to the question, but it is a step in the direction of a solution to the problem that led me to ask the question. If you have the same problem, this may be helpful.
Although I'm still interested in solving the mystery related to the failing test, I found a way to set my pane titles more easily1.
There is a pane_title property that can be used in your pane-border-format:
tmux set pane-border-format "#{pane_title}"
If you set this format, then you can set the title with printf and escape sequences:
printf '\033]2;%s\033\\' 'your desired title'
(I had read about the printf technique elsewhere, both on and off SO, but it fails if you don't have the proper format including pane_title. No where else did I see these two things mentioned together. Without the combination, it fails. Assuming that the default format is set is not a safe assumption.)
A complete answer is still useful, so I could do things like this:
tmux set pane-border-format " #P: #{?pane_title,#{pane_title},`tmux_pane_title \"#{session_name}\" \"#{pane_current_command}\" \"#{pane_current_path}\"`} "
That would choose an explicit title if one were set, and default to the function to choose one. So please don't close this question as a duplicate of others that relate to setting tmux pane titles. IT IS DIFFERENT.
1In other words, I solved the problem but I didn't answer the question. Many people think SO is a problem-solving site, but it describes itself as a question & answer site. I doubt if many people have given this distinction much thought, but they are very different things.

How to delete a row in a csv file with powershell in R?

Good morning,
I'm new about powershell and I'd like to ask you if somebody can help me.
I have a big csv file around 3.5gb and my goal is to load it with fread (a data.table function) in R environment, but this function makes a error.
> n_a<-fread("C:/x/xy/xyz/name_file.csv",sep=";", fill = TRUE)
The error is:
Warning message:
In fread("C:/x/xy/xyz/name_file.csv") :
Stopped early on line 458945. Expected 29 fields but found 30. Consider fill=TRUE and comment.char=. First discarded non-empty line
I tried to use different way (I putted in my code fill=true, but doesn't work) to solve the problem, but I couldn't do it.
After different researches I found this kind of solution (always to do in R):
>system("powershell Get-Content C:/a/b/c/file.csv | Select -Index (0..458944 + 1000000) > output.csv")
The focus about the use of powershell in R is to delete a specific row and to load with fread the file.
My question is:
How I can delete a specific row in a csv in powershell but without specifying the length of the matrix?
Thank you in advance for every type of help.
Francesco
I'd hazard a guess that the invalid row's location is not known. In such a case, it might be sensible to read the original file and create a new file that contains only valid data. What's more, if the source data would benefit of manipulation, it can be done before reading it into R.
A file as large as 3,5 GiB is a bit on the large side to read in memory as such. Sure, it can be done in the days of 64 bit systems, but for simple row processing it's unwieldy. A scalable solution uses .Net methods and row-by-row approach.
To process a file on row-by-row basis, use .Net methods for efficient row reading. A StringBuilder is created to store rows that contain valid data, others are discarded. The StringBuilder is flushed on disk every so often. Even on days of SSDs, a write operation for each row is relatively slow in respect to writing in a bulk of, say, 10 000 rows a time.
$sb = New-Object Text.StringBuilder
$reader = [IO.File]::OpenText("MyCsvFile.csv")
$i = 0
$MaxRows = 10000
$colonCount = 30
while($null -ne ($line = $reader.ReadLine())) {
# Split the line on semicolons
$elements = $line -split ';'
# If there were $colonCount elements, add those to builder
if($elements.count -eq $colonCount) {
# If $line's contents need modifications, do it here
# before adding it into the builder
[void]$sb.AppendLine($line)
++$i
}
# Write builder contents into file every now and then
if($i -ge $MaxRows) {
add-content "MyCleanCsvFile.csv" $sb.ToString()
[void]$sb.Clear()
$i = 0
}
}
# Flush the builder after the loop if there's data
if($sb.Length -gt 0) {
add-content "MyCleanCsvFile.csv" $sb.ToString()
}
This is easy done in powershell: Read csv in generic list, remove line and write back:
Add-Type -AssemblyName System.Collections
[System.Collections.Generic.List[string]]$csvList = #()
$csvFile = 'C:\test\myfile.csv'
$csvList = [System.IO.File]::ReadLines( $csvFile )
$lineToDelete = 2
[void]$csvList.RemoveAt( $lineToDelete - 1 )
[System.IO.File]::WriteAllLines( $csvFile, $csvList ) | Out-Null
vonPryz's helpful answer offers the best solution, given the size of your input file.
The following works too, but will be slow - in general, due to the overhead of using a pipeline, but also because Get-Content itself is slow due to decorating each line read with additional properties (see green-lighted, but not yet implemented GitHub suggestion #7537):
# Exclude line number 458945 (0-based index 458944)
Get-Content C:/a/b/c/file.csv | Select-Object -SkipIndex 458944 > output.csv
The beneficial flip side of use of the pipeline is that it acts as a memory throttle, so the above command can be used to process arbitrarily large files (though it may take a long time).

Jupyter Notebook different ways to display out

There seems to be 3 ways to display output in Jupyter:
By using print
By using display
By just writing the variable name
What is the exact difference, especially between number 2 and 3?
I haven't used display, but it looks like it provides a lot of controls. print, of course, is the standard Python function, with its own possible parameters.
But lets look at a simple numpy array in Ipython console session:
Simply giving the name - the default out:
In [164]: arr
Out[164]: array(['a', 'bcd', 'ef'], dtype='<U3')
This is the same as the repr output for this object:
In [165]: repr(arr)
Out[165]: "array(['a', 'bcd', 'ef'], dtype='<U3')"
In [166]: print(repr(arr))
array(['a', 'bcd', 'ef'], dtype='<U3')
Looks like the default display is the same:
In [167]: display(arr)
array(['a', 'bcd', 'ef'], dtype='<U3')
print on the other hand shows, as a default, the str of the object:
In [168]: str(arr)
Out[168]: "['a' 'bcd' 'ef']"
In [169]: print(arr)
['a' 'bcd' 'ef']
So at least for a simple case like this the key difference is between the repr and str of the object. Another difference is which actions produce an Out, and which don't. Out[164] is an array. Out[165] (and 168) are strings. print and display display, but don't put anything on the Out list (in other words they return None).
display can return a 'display' object, but I won't get into that here. You can read the docs as well as I can.

Lua: Doing arithmetic in for k,v in pairs(tbl) loops

I have a table such as the following:
mafiadb:{"Etzli":{"alive":50,"mafia":60,"vigilante":3,"doctor":4,"citizen":78,"police":40},"Charneus":{"alive":29,"mafia":42,"vigilante":6,"doctor":14,"citizen":53,"police":33}}
There are more nested tables, but I'm just trying to keep it simple for now.
I run the following code to extract certain values (I'm making an ordered list based on those values):
sortmaf={}
for k,v in pairs(mafiadb) do
sortmaf[k]=v["mafia"]
end
That's one of the codes I run. The problem I'm running into is that it doesn't appear you can do arithmetic in a table loop. I tried:
sortpct={}
for k,v in pairs(mafiadb) do
sortpct[k]=(v["alive"]*100)/(v["mafia"]+v["vigilante"]+v["doctor"]+v["citizen"]+v["police"])
end
It returns that I'm attempting to do arithmetic on field "alive." What am I missing here? As usual, I appreciate any consideration in answering this question!
Editing:
Instead of commenting on the comment, I'm going to add additional information here.
The mafiadb database I've posted IS the real database. It's just stripped down to two players instead of the current 150+ players I have listed in it. It's simply structured as such:
mafiadb = {
Playername = {
alive = 0
mafia = 0
vigilante = 0
doctor = 0
police = 0
citizen = 0
}
}
Add a few hundred more playernames, and there you have it.
As for the error message, the exact message is:
attempt to perform arithmetic on field 'alive' (nil value)
So... I'm not sure what the problem is. In my first code, the one with sortmaf, it works perfectly, but suddenly, it can't find v["alive"] as a value when I'm trying to do arithmetic? If I just put v["alive"] by itself, it's suddenly found and isn't nil any longer. I hope this clarifies a bit more.
This looks like a simple typo to me.
Some of your 150 characters is not well written - probably they don't have an "alive" property, or it's written incorrectly, or it's not a number. Try this:
for k,v in pairs(mafiadb) do
if type(v.alive) ~= 'number' then
print(k, "doesn't have a correct alive property")
end
end
This should print the names of the "bad" characters.

Customize zsh's prompt when displaying previous command exit code

Zsh includes the ability to display the return code/exit code of the previous command in the prompt by using the %? escape sequence.
However I would like to have the following prompt:
user#host ~ [%?] %
when the exit code is different from 0 and:
user#host ~ %
when exit code is 0.
If I use %? alone it is always displayed, even if %? is 0.
In addition I want the square brackets but only when the exit code not 0.
What is the simplest way to do this?
Add this in the position in PS1 where you want the exit code to appear:
%(?..[%?] )
It's a conditional expression. The part between the two dots (nothing in this case) is output if the expression before the first dot is true. The part after the second dot is output if it's false.
For example:
PS1='%n%m %~ %(?..[%?] )%# '
Alternatively, you can:
setopt PRINT_EXIT_VALUE
to always print a newline showing previous return value.
I don't prefer this for ordinary use, but it is often good for debugging shell scripts.

Resources