Problem is very simple. let think I have two simple for loop in Xquery.
for $i in 1 to 3
return <oneEval>{$i}</oneEval>
for $j in 10 to 30
return <tenEval>{$j}</tenEval>
If I run individually it is fine. But if I want to run concurrently it gives error. Can't I use more one 'return' in a Xquery? Can anybody please explain. Thanks in advance.
Try turning it into a sequence. Wrap the entire xquery in parentheses and separate the for loops with a comma.
Example:
(
for $i in 1 to 3
return <oneEval>{$i}</oneEval>
,
for $j in 10 to 30
return <tenEval>{$j}</tenEval>
)
You can reformat the example. I kept the parens and comma on separate lines so it would be easier to see the additions.
Related
let $removeLastCR:=fn:replace($output.output_FileContent , '(\r?\n|\r)$', '')
let $lines := tokenize($removeLastCR, '\n')
return
for $line at $counter in $lines
let $x :=
for $i in fn:tokenize($line,'"')
return
if(fn:starts-with($i,',') and fn:ends-with($i,','))
then fn:substring($i,2,fn:string-length($i)-2)
else
if(fn:starts-with($i,','))
then fn:substring-after($i,',')
else
if(fn:ends-with($i,','))
then fn:substring($i,1,fn:string-length($i)-1)
else $i
let $fields :=
for $j at $k in $x
return
if(fn:starts-with($line,'"'))
then
if($k mod 2 = 0)
then fn:tokenize($j,',')
else $j
else
if($k mod 2 = 0)
then $j
else fn:tokenize($j,',')
return
The real issue is that I am trying to understand why the parsing fails for the below data record, but works for the rest of the data in the file (File is a .CSV file):
xyz#example.com,XYZ LastName,Merchant,15/08/2022,199.98,USD,199.98,USD,61001,,,xyz#example.com | R1111111,"Qty 10- 4"" X 4"" X 5.7"" - Color: Custom Box 1",,XYZ,CC 1 August,R1111111,P&E \: PS mama,,policyid,CCP,https://www.example.com/report?reportID=R1111111,cdf,1234XXXXXX5678,https://example.com,
For the above record, the code should have parsed each comma separated value into it's own field,(Field1: xyz#example.com, Field2: XYZ LastName etc) but I think it falls apart on the field value "Qty 10- 4"" X 4"" X 5.7"" - Color: Custom Box 1". It SHOULD parse this whole value into 1 field, but it only gets "Qty 10- 4" into Field#13. And all the fields after this are also all not parsed properly.
So I was trying to better understand this code (someone else wrote it) so i can make the appropriate changes to handle this scenario.
There are many variants of CSV syntax, and it looks as if this data file is using a convention of escaping " within a quoted field by doubling the quotation marks. But the query code that parses the CSV is making no attempt to handle such escaped quotation marks.
It's easy to tell you what each line of code does, but I suspect that's not your problem. What's harder is to understand the overall logic.
The first part creates a variable $x by tokenizing on " and removing leading and trailing commas from every token. That makes no sense to me. The second part then takes the tokens that weren't in quotes and splits them on "," separators.
I think this code is already fairly broken, and it certainly can't be extended to handle quotes that are escaped by doubling. It needs to be rewritten. I don't think it can be done with simple tokenisation.
A bit of googling shows a variety of attempts at CSV to XML converters. Unfortunately few of them are very explicit about exactly what flavour of CSV they handle, and many don't even attempt to handle commas within quoted fields. Not very satisfactory, but I'm afraid that writing a better one isn't possible within the 10 minutes I allow myself for answering StackOverflow questions.
I have multiple files numbered as file_1.mol file_2.mol and so on. I'd like to concatenate the files in groups of 20 files, creating the file_1-20.mol. Is it possible to define an interval in the 'cat' command to get this result?
thanks in advance
You can use brace expansion:
cat file_{1..20}.ml > file_1-20.mol
or make a shell function that you can pass the start and end numbers to:
copy_range() { cat file_{$1..$2}.mol > "file_${1}-${2}.mol" }
copy_range 1 20
I am trying to subtracts one count value from another but,I am facing problem in following code :
count=$?
count1=$?
(then some operations and above count values got some value suppose 1,2 respectively)
$count=$count1 - $count ==> Here it should get : 2-1=1 )
I don't know exact syntax for this so, can any one help me please?
You can use the shell's expression syntax:
count=$(($count1-$count))
the $ prefix on variables is optional inside $(()), so this can also be written as:
count=$((count1-count))
Unix provides you the command expr that lets you evaluate any arithmetic expression you want. At shell prompt try :
expr 2 - 3 + 5 '*' 8
Remember that * is used as wildcard so you need to un-specialized it in any way you want.
Then now, you could use ` to evaluate an expression at any place :
count=`expr $count1 - $count`
Be aware that all arguments MUST be separated with spaces.
This will work for Bourne-shell which is the one recommended for shell-scripts.
I am hoping to perform a series of edits to a large text file composed almost entirely of single letters, seperated by spaces. The file is about 300 rows by about 400,000 columns, and about 250 MB.
My goal is to tranform this table using a series of steps, for eventual processing with another language (R, probably). I don't have much experience working with big data files, but PERL has been suggested to me as the best way to go about this. Please let me know if there is a better way :).
So, I am hoping to write a PERL script that does the following:
Open file, edit or write to a new file the following:
remove columns 2-6
merge/concatenate pairs of columns, starting with column 2 (so, merge column 2-3,4-5, etc)
replace each character pair according to sequential conditional algorithm running accross each row:
[example PSEUDOCODE: if character 1 of cell = character 2 of cell=a, cell=1
else if character 1 of cell = character 2 of cell=b, cell=2
etc.] such that except for the first column, the table is a numerical matrix
remove every nth column, or keep every nth column and remove all others
I am just starting to learn PERL, so I was wondering if these operations were possible in PERL, whether PERL would be the best way to do them, and if there were any suggestions for syntax on these operations in the context of reading/writing to a file.
I'll start:
use strict;
use warnings;
my #transformed;
while (<>) {
chomp;
my #cols = split(/\s/); # split on whitespace
splice(#cols, 1,6); # remove columns
push #transformed, $cols[0];
for (my $i = 1; $i < #cols; $i += 2) {
push #transformed, "$cols[$i]$cols[$i+1]";
}
# other transforms as required
print join(' ', #transformed), "\n";
}
That should get you on your way.
You need to post some sample input and expected output or we're just guessing what you want but maybe this will be a start:
awk '{
printf "%s ", $1
for (i=7;i<=NF;i+=2) {
printf "%s%s ", $i, $(i+1)
}
print ""
}' file
I'm trying to learn how to configure my .vimrc file with my own functions.
I'd like to write a function that traverses every line in a file and counts the total number of characters, but ignores all whitespace. This is for a programming exercise and as a stepping stone to more complex programs (I know there are other ways to get this example value using Vim or external programs).
Here's what I have so far:
function countchars()
let line = 0
let count = 0
while line < line("$")
" update count here, don't count whitespace
let line = getline(".")
return count
endfun
What functional code could I replace that commented line with?
If I understand the question correctly, you're looking to count the number of non-whitespace characters in a line. A fairly simple way to do this is to remove the whitespace and look at the length of the resulting line. Therefore, something like this:
function! Countchars()
let l = 1
let char_count = 0
while l <= line("$")
let char_count += len(substitute(getline(l), '\s', '', 'g'))
let l += 1
endwhile
return char_count
endfunction
The key part of the answer to the question is the use of substitute. The command is:
substitute(expr,pattern,repl,flags)
expr in this case is getline(l) where l is the number of the line being iterated over. getline() returns the content of the line, so this is what is being parsed. The pattern is the regular expression \s which matches any single whitespace character. It is replaced with '', i.e. an empty string. The flag g makes it repeat the substitute as many times as whitespace is found on the line.
Once the substitution is complete, len() gives the number of non-whitespace characters and this is added to the current value of char_count with +=.
A few things that I've changed from your sample:
The function name starts with a capital letter (this is a requirement for user defined functions: see :help user-functions)
I've renamed count to char_count as you can't have a variable with the same name as a function and count() is a built-in function
Likewise for line: I renamed this to l
The first line in a file is line 1, not line 0, so I initialised l to 1
The while loop counted up to but not including the last line, I assume you wanted all the lines in the file (this is probably related to the line numbering starting at 1): I changed your code to use <= instead of <
Blocks aren't based on indentation in vim, so the while needs an endwhile
In your function, you have let line = getline('.')
I added a ! on the function definition as it makes incremental development much easier (everytime you re-source the file, it will override the function with the new version rather than spitting out an error message about it already existing).
Incrementing through the file works slightly differently...
In your function, you had let line = getline('.'). Ignoring the variable name, there are still some problems with this implementation. I think what you meant was let l = line('.'), which gives the line number of the current line. getline('.') gives the contents of the current line, so the comparison on the while line would be comparing the content of the current line with the number of the last line and this would fail. The other problem is that you're not actually moving through the file, so the current line would be whichever line you were on when you called the function and would never change, resulting in an infinite loop. I've replaced this with a simple += 1 to step through the file.
There are ways in which the current line would be a useful way to do this, for example if you were writing a function with that took a range of lines, but I think I've written enough for now and the above will hopefully get you going for now. There are plenty of people on stackoverflow to help with any issues anyway!
Have a look at:
:help usr_41.txt
:help function-list
:help user-functions
:help substitute()
along with the :help followed by the various things I used in the function (getline(), line(), let+= etc).
Hope that was helpful.
This approach uses lists:
function! Countchars()
let n = 0
for line in getline(1,line('$'))
let n += len(split(line,'\zs\s*'))
endfor
return n
endfunction
I suppose you have already found the solution.
Just for info:
I use this to count characters without spaces in Vim:
%s/\S/&/gn