I want to write a header for an output file that's aligned with several variables, something like:
var1 var2 ................. varX
value value value
So I'd rather avoid manually padding every variable name.
From reading the docs, a format specifier when calling write() is the preferred method.
write(1, "(a23)") "var1", "var2", !etc.
But this inserts a newline after every variable.
write(1, "(a23)", advance="no") does NOT fix this, it only suppresses the newline after the final variable is written. write(1, *) DOES print a newline only after the final variable, but then I lose the spacing.
Tested in GNU Fortran 10.2 with -std=f2003.
Ideas?
"(a23)" is the format for a single character variable. When the format finishes, but there are still items to be written in the input list, the format is interpreted from the beginning, but a new line character (end of record) is added.
You have to use a format for multiple items: "(3a23)", "(3(a23))", "(9999(a23))" or even "(*(a23))"
See also https://stackoverflow.com/a/9881337/721644
Note that you can also use the t or tr or x descriptor to insert padding.
Related
I'm working on a small text file with a list of words in it that I want to add a new word to, and then sort. The file doesn't have a newline at the end when I start, but does after the sort. Why? Can I avoid this behavior or is there a way to strip the newline back out?
Example:
words.txt looks like
apple
cookie
salmon
I then run printf "\norange" >> words.txt; sort words.txt -o words.txt
I use printf rather than echo figuring that'll avoid the newline, but the file then reads
apple
cookie
orange
salmon
#newline here
If I just run printf "\norange" >> words.txt orange appears at the bottom of the file, with no newline, ie;
apple
cookie
salmon
orange
This behavior is explicitly defined in the POSIX specification for sort:
The input files shall be text files, except that the sort utility shall add a newline to the end of a file ending with an incomplete last line.
As a UNIX "text file" is only valid if all lines end in newlines, as also defined in the POSIX standard:
Text file - A file that contains characters organized into zero or more lines. The lines do not contain NUL characters and none can exceed {LINE_MAX} bytes in length, including the newline character. Although POSIX.1-2008 does not distinguish between text files and binary files (see the ISO C standard), many utilities only produce predictable or meaningful output when operating on text files. The standard utilities that have such restrictions always specify "text files" in their STDIN or INPUT FILES sections.
Think about what you are asking sort to do.
You are asking it "take all the lines, and sort them in order."
You've given it a file containing four lines, which it splits to the following strings:
"salmon\n"
"cookie\n"
"orange"
It sorts these for you dutifully:
"cookie\n"
"orange"
"salmon\n"
And it then outputs them as a single string:
"cookie
orangesalmon
"
That is almost certainly exactly what you do not want.
So instead, if your file is missing the terminating newline that it should have had, the sort program understands that, most likely, you still intended that last line to be a line, rather than just a fragment of a line. It appends a \n to the string "orange", making it "orange\n". Then it can be sorted properly, without "orange" getting concatenated with whatever line happens to come immediately after it:
"cookie\n"
"orange\n"
"salmon\n"
So when it then outputs them as a single string, it looks a lot better:
"cookie
orange
salmon
"
You could strip the last character off the file, the one from the end of "salmon\n", using a range of handy tools such as awk, sed, perl, php, or even raw bash. This is covered elsewhere, in places like:
How can I remove the last character of a file in unix?
But please don't do that. You'll just cause problems for all other utilities that have to handle your files, like sort. And if you assume that there is no terminating newline in your files, then you will make your code brittle: any part of the toolchain which "fixes" your error (as sort kinda does here) will "break" your code.
Instead, treat text files the way they are meant to be treated in unix: a sequence of "lines" (strings of zero or more non-newline bytes), each followed by a newline.
So newlines are line-terminators, not line-separators.
There is a coding style where prints and echos are done with the newline leading. This is wrong for many reasons, including creating malformed text files, and causing the output of the program to be concatenated with the command prompt. printf "orange\n" is correct style, and also more readable: at a glance someone maintaining your code can tell you're printing the word "orange" and a newline, whereas printf "\norange" looks at first glance like it's printing a backslash and the phrase "no range" with a missing space.
I am writing a shell script in perl that takes values from two databases and compares them. When the script is finished it outputs a report that is supposed to be formatted this way:
Table Name Date value from Database 1 value from Database 2 Difference
The output is printed into a report file, but even when it is output to the command console it looks like this:
tablename 2017-06-20 7629628
7629628
0
Here's my code that makes the string then outputs it to the file:
$outputstring="$tablelist[0] $DATErowcount0[$output_iteration] $rowcount0[$output_iteration] $TDrowcount0[$output_iteration] $count_dif\n";
print FILE $outputstring;
There seems to be a newline character hidden after $rowcount0[$output_iteration] and before $count_dif. What do I need to do to fix this/print it all in one line?
To fill the arrays with values, values are read from files created by SQL commands.
Here's some of the code:
`$num_from_TDfile=substr $r2, 16;
$date_from_TDfile = substr $r2, 0, 12;
$TDrowcount0[$TDnum_rows0]=$num_from_TDfile;
$DATETDrowcount0[$TDnum_rows0]=$date_from_TDfile;
$TDnum_rows0=$TDnum_rows0+1;`
Adding the chomp to each of the strings taken from the files as suggested by tadman fixed the output so that it was all on one line rather than three lines as in the question's example.
I am trying to write a shell script in which I want to assign certain characters to some variables. But since I want to cycle through a set of characters, I can't just write char1='A'. I want to be able to assign 'A' to the variable char1 using its ASCII cose number. I am also very new to shell scripting, so, if a detailed explanation of the command I need to use would be much appreciated. Thanks!
The following command will assign 65 (ASCII value of "A") to the variable char1:
char1=$(printf "%d" "'A")
The command printf is similar to the C function printf() which is used to print preformatted text. Using a quote(') before a character prints the ASCII equivalent of the character.
I am trying to get variables into a block of text which will later be echoed to a file.
Problem is the $VAR is not getting converted into the variable's value ??
VAR="SOME Value"
read -d '' WPA <<"BLOCK"
Description='WIFI'
Interface=wlan0
Connection=wireless
IP=dhcp
Security=wpa
Key=$VAR
BLOCK
echo "$WPA"
Also, is it possible to append further text to the WPA Block ?
When you quote the delimeter of a heredoc, variables are not interpolated. Just drop the quotes:
read -d '' WPA <<BLOCK
Description='WIFI'
Interface=wlan0
Connection=wireless
IP=dhcp
Security=wpa
Key=$VAR
BLOCK
Why don't you just say
WPA="Description='WIFI'
Interface=wlan0
Connection=wireless
IP=dhcp
Security=wpa
Key=$VAR
"
?
There's not really a need to use read in your case.
If you want to echo append text to $WPA, do it like this:
WPA="$WPA
first appended line
second appended line
"
but be aware that you insert an extra newline this way - $WPA had a newline at the end and there's another one at the beginning of the new text. To avoid this, use
WPA="${WPA}first appended line
second appended line
"
The {} quotation delimits the variable name. Using
WPA="$WPAfirst appended line
would look for a variable named WPAfirst.
is it possible to append further text to the WPA Block ?
$WPA is just a normal shell variable (that happens to contain a multi-line string), so you can append to it with +=; e.g.:
WPA+=$'\nanother line\nand another'
If you wanted to append the content of another heredoc, assign it to a separate variable and append that to WPA (but, as #GuntramBlohm points out, you can just as easily assign/append a multi-line string directly).
I have a text file:
Function Description
concat Returns the concatenation of the arguments.
contains Returns true if the first argument string contains the second argument string; otherwise returns false.
I'd like to wrap the text on column#2, the result should be:
Function Description
concat Returns the concatenation
of the arguments.
contains Returns true if the first
argument string contains
the second argument
string; otherwise returns
false.
How to do it in vim or shell quickly? Thank you for any suggestions.
The issue can be easily solved in Vim by using the indentexpr option. Set
it to the number of characters designated for the first column,
:set inde=16
then format the text as usual with the gq or gw families of commands.
I don't think this qualifies as "quickly", and I hope someone out there has a better answer, but this is the best I could come up with in vim:
1) Set textwidth to the desired width of your second column:
:set tw=60
2) Mark the first-column words with something special (to be removed later - any non-normal text will do, I'm using jjj here) (using g!/^$/ to ignore empty lines):
:%g!/^$/s/^/jjj/
3) Put the second column text on a separate line:
:%s/ \</ \r/
4) Rewrap all the second-column lines to the desired width:
:%g!/^jjj/normal gqq
5) Join the first line of each second-column paragraph with its first-column word (should preserve the space that was after the first-column words at the beginning):
:%g/^jjj/join
6) Indent all the remaining second-column lines the appropriate amount to line them up (use however many >>s are needed - there may be a way to make vim check the length of the last first-column line and insert that number of spaces instead of using this method):
:%g!/^jjj/normal >>>>>>>>
7) Finally remove the first-column marker from the first columns:
:%s/^jjj//
Not worth it for your example, but if the file's large enough, it's better than doing it by hand...
:set tw=80 #or :set textwidth=80
Would wrap text to 80 chars.
Then you can type in command mode:
gg #go to the top
and then
gqG #apply reformat to the end
Reference:
http://www.cs.swarthmore.edu/help/vim/reformatting.html