Here's an example in python3 of what I want to do in Fortran:
str1 = "Hello"
str2 = " World!"
print(str1 + str2)
# And then the result would be "Hello World!"
When I do:
print "(A)", str1, str2
It puts it on a separate line. If anyone knows how to help please answer.
The literal answer to string concatenation, using the // operator, is given in another answer. Note, particularly, that you likely want to TRIM the first argument.
But there is another interesting concept your question raises, and that is format reversion.
With the format (A) we have one format item. In the output list str1, str2 we have two output items. In a general output statement we apply each format item (with repeat counts) to a corresponding output item. So, str1 is processed with the first format item A, and a string appears.
Come the second output item str2 we've already used the single format item, reaching the end of the format item list. The result is that we see this format reversion: that is, we go back to the first item in the list. After, crucially, we start a new line.
So, if we just want to print those two items to one line (with no space or blank line between them) we could use (neglecting trimming for clarity)
print "(A)", str1//str2
or we could use a format which hasn't this reversion
print "(2A)", str1, str2
print "(A, A)", str1, str2
The first concatenates the two character variables to give one, longer, which is then printed as a single output item. The second prints both individually.
Coming to your particular example
character(12), parameter :: str1="Hello" ! Intentionally longer - trailing blanks
character(12), parameter :: str2=" World!"
print "(2A)", TRIM(str1), TRIM(str2)
end
will have output like
Hello World!
with that middle space because TRIM won't remove the leading space from str2. More widely, though we won't have the leading space there for us, and we want to add it in the output.
Naturally, concatenation still works (I'm back to assuming no-trimming)
character(*), parameter :: str1="Hello" ! No trailing blank
character(*), parameter :: str2="World!"
print "(A)", str1//" "//str2
end
but we can choose our format, using the X edit descriptor, to add a space
print "(2(A,1X))", str1, str2
print "(A,1X,A)", str1, str2
print "(2(A,:,1X))", str1, str2
where this final one has the useful colon edit descriptor (outside scope of this answer).
Probably close to what you want:
Concatenate two strings in Fortran
zz = trim(xx) // trim(yy)
More info
Bing
It looks like this is covered but another useful feature, if you want to print a lot of data on the same line is the following:
character(len=32),dimension(100) :: str
do i=1,100
write(*,fmt="(A)", advance='no') str(i)
end do
write(*,*) ! to go to the next line when you are done
This will print 100 characters on the same line because of advance='no'
You can use another variable to put those into it, and write those two strings in that new variable:
Program combineString
character(len=100) :: text1, text2, text
text1 = "Hello,"
text2 = "My name is X"
write(text,'(A6, X, A20)') text1, text2
write(*,*) text
End Program
And output is:
Hello, My name is X
Related
how can I extract a few words separated by symbols in a string so that nothing is extracted if the symbols change?
for example I wrote this code:
function split(str)
result = {};
for match in string.gmatch(str, "[^%<%|:%,%FS:%>,%s]+" ) do
table.insert(result, match);
end
return result
end
--------------------------Example--------------------------------------------
str = "<busy|MPos:-750.222,900.853,1450.808|FS:2,10>"
my_status={}
status=split(str)
for key, value in pairs(status) do
table.insert(my_status,value)
end
print(my_status[1]) --
print(my_status[2]) --
print(my_status[3]) --
print(my_status[4]) --
print(my_status[5]) --
print(my_status[6]) --
print(my_status[7]) --
output :
busy
MPos
-750.222
900.853
1450.808
2
10
This code works fine, but if the characters and text in the str string change, the extraction is still done, which I do not want to be.
If the string change to
str = "Hello stack overFlow"
Output:
Hello
stack
over
low
nil
nil
nil
In other words, I only want to extract if the string is in this format: "<busy|MPos:-750.222,900.853,1450.808|FS:2,10>"
In lua patterns, you can use captures, which are perfect for things like this. I use something like the following:
--------------------------Example--------------------------------------------
str = "<busy|MPos:-750.222,900.853,1450.808|FS:2,10>"
local status, mpos1, mpos2, mpos3, fs1, fs2 = string.match(str, "%<(%w+)%|MPos:(%--%d+%.%d+),(%--%d+%.%d+),(%--%d+%.%d+)%|FS:(%d+),(%d+)%>")
print(status, mpos1, mpos2, mpos3, fs1, fs2)
I use string.match, not string.gmatch here, because we don't have an arbitrary number of entries (if that is the case, you have to have a different approach). Let's break down the pattern: All captures are surrounded by parantheses () and get returned, so there are as many return values as captures. The individual captures are:
the status flag (or whatever that is): busy is a simple word, so we can use the %w character class (alphanumeric characters, maybe %a, only letters would also do). Then apply the + operator (you already know that one). The + is within the capture
the three numbers for the MPos entry each get (%--%d+%.%d+), which looks weird at first. I use % in front of any non-alphanumeric character, since it turns all magic characters (such as + into normal ones). - is a magic character, so it is required here to match a literal -, but lua allows to put that in front of any non-alphanumerical character, which I do. So the minus is optional, so the capture starts with %-- which is one or zero repetitions (- operator) of a literal - (%-). Then I just match two integers separated by a dot (%d is a digit, %. matches a literal dot). We do this three times, separated by a comma (which I don't escape since I'm sure it is not a magical character).
the last entry (FS) works practically the same as the MPos entry
all entries are separated by |, which I simply match with %|
So putting it together:
start of string: %<
status field: (%w+)
separator: %|
MPos (three numbers): MPos:(%--%d+%.%d+),(%--%d+%.%d+),(%--%d+%.%d+)
separator: %|
FS entry (two integers): FS:(%d+),(%d+)
end of string: %>
With this approach you have the data in local variables with sensible names, which you can then put into a table (for example).
If the match failes (for instance, when you use "Hello stack overFlow"), nil` is returned, which can simply be checked for (you could check any of the local variables, but it is common to check the first one.
Let's say I have a string with the contents
local my_str = [[
line1
line2
line4
]]
I'd like to get the following table:
{"line1","line2","","line4"}
In other words, I'd like the blank line 3 to be included in my result. I've tried the following:
local result = {};
for line in string.gmatch(my_str, "[^\n]+") do
table.insert(result, line);
end
However, this produces a result which will not include the blank line 3.
How can I make sure the blank line is included? Am I just using the wrong regex?
Try this instead:
local result = {};
for line in string.gmatch(my_str .. "\n", "(.-)\n") do
table.insert(result, line);
end
If you don't want the empty fifth element that gives you, then get rid of the blank line at the end of my_str, like this:
local my_str = [[
line1
line2
line4]]
(Note that a newline at the beginning of a long literal is ignored, but a newline at the end is not.)
You can replace the + with *, but that won't work in all Lua versions; LuaJIT will add random empty strings to your result (which isn't even technically wrong).
If your string always includes a newline character at the end of the last line like in your example, you can just do something like "([^\n]*)\n" to prevent random empty strings and the last empty string.
In Lua 5.2+ you can also just use a frontier pattern to check for either a newline or the end of the string: [^\n]*%f[\n\0], but that won't work in LuaJIT either.
If you need to support LuaJIT and don't have the trailing newline in your actual string, then you could just add it manually:
string.gmatch(my_str .. "\n", "([^\n]*)\n")
I am trying to gsplit my text into multiple tables using a pattern.
So this is my input.
\x10Hello\x0AWorld
This is what I expect in my output,
\x0A <- similar inputs will always be 4 chars long
{{'\x10', 'Hello'}, {'\x0A', 'World'}}
This is what I have tried so far.
local function splitIntoTable(input)
local output = {}
for code, text in (input):gmatch('(\\x%x+)(.*)') do
print(code .. ' ' .. text);
table.insert(output, { code, text })
end
return output
end
I made 2 regex groups in gmatch the first group is for the hex and the second group is for the text, I am not sure why this isn't working. The print statement never gets executed so the loop is never being used.
The pattern '\\x%x+' matches a literal backslash, an x, and a sequence of hex digits. It does not match the ASCII character generated by a hexadecimal escape such as '\x0A'.
You need to replace it with a character class in square brackets such as '[\x10\x0A]'. You will have to fill in the character class with whatever ASCII characters (or other bytes) you are expecting in that position in the match.
Unfortunately, this pattern will only match once in a string like '\x10Hello\x0AWorld'. The second part of the pattern also needs to be modified.
local function splitIntoTable(input)
local output = {}
for code, text in (input):gmatch('([\x10\x0A])(.*)') do
print(code .. ' ' .. text);
table.insert(output, { code, text })
end
return output
end
I'm trying to phrase a string for a hobby project and I'm self taught from code snips from this site and having a hard time working out this problem. I hope you guys can help.
I have a large string, containing many lines, and each line has a certain format.
I can get each line in the string using this code...
for line in string.gmatch(deckData,'[^\r\n]+') do
print(line) end
Each line looks something like this...
3x Rivendell Minstrel (The Hunt for Gollum)
What I am trying to do is make a table that looks something like this for the above line.
table = {}
table['The Hunt for Gollum'].card = 'Rivendell Minstrel'
table['The Hunt for Gollum'].count = 3
So my thinking was to extract everything inside the parentheses, then extract the numeric vale. Then delete the first 4 chars in the line, as it will always be '1x ', '2x ' or '3x '
I have tried a bunch of things.. like this...
word=str:match("%((%a+)%)")
but it errors if there are spaces...
my test code looks like this at the moment...
line = '3x Rivendell Minstrel (The Hunt for Gollum)'
num = line:gsub('%D+', '')
print(num) -- Prints "3"
card2Fetch = string.sub(line, 5)
print(card2Fetch) -- Prints "Rivendell Minstrel (The Hunt for Gollum)"
key = string.gsub(card2Fetch, "%s+", "") -- Remove all Spaces
key=key:match("%((%a+)%)") -- Fetch between ()s
print(key) -- Prints "TheHuntforGollum"
Any ideas how to get the "The Hunt for Gollum" text out of there including the spaces?
Try a single pattern capturing all fields:
x,y,z=line:match("(%d+)x%s+(.-)%s+%((.*)%)")
t = {}
t[z] = {}
t[z].card = y
t[z].count = x
The pattern reads: capture a run of digits before x, skip whitespace, capture everything until whitespace followed by open parenthesis, and finally capture everything until a close parenthesis.
gsub(/^/, "\t" * num)
What character is being substituted?
No character is being substituted, it is just inserting num tabs at the beginning so you could say that it is substituting the zero width "beginning of line" marker. Whoever wrote that would have been better off with something more like this:
tabbed = "\t" * num + original
A regular expression really isn't the right tool for simple string concatenation.
Clarification: If you're expecting your string to contain multiple lines then using:
gsub(/^/, "\t" * num)
to prefix all the lines with tabs is a reasonably thing to do and less noisy than splitting, prefixing, and re-joining. If you're only expecting to deal with a single line in your string then simple string concatenation would be the better choice.
^ means "start of line" in regex syntax, so this will insert num tab characters at the beginning of every line. Technically you could say that it replaces the empty string at the start of every line.