Weird behavior of sed's backreference - sed

We have the following line of text:
| ![](/img/2016/12/020.jakis-tam-text1.png#medium) | ![](/img/2016/12/021.jakis-tam-text2.png#medium) | ![](/img/2016/12/022.jakis-tam-text3.png#medium) |
As you can see, the line of text simply consists of three similar phrases, which can be matched and changed (separately) using the following sed expression:
sed -n 's#| !\[.*\](\(\/img\/\)\([0-9]*\/[0-9]*\/[0-9]*\)\.\(.*\)\.\(.*\)) |#| ![\3](\1\2.\3.\4) |#p'
If we had just one phrase (instead of the given three), the result would be the following:
$ echo '| ![](/img/2016/12/020.jakis-tam-text1.png#medium) |' | sed -n 's#| !\[.*\](\(\/img\/\)\([0-9]*\/[0-9]*\/[0-9]*\)\.\(.*\)\.\(.*\)) |#| ![\3](\1\2.\3.\4) |#p'
| ![jakis-tam-text1](/img/2016/12/020.jakis-tam-text1.png#medium) |
But when we have two or thee phrases, the result always points to the last matched phrase:
Here's an example with two matches:
$ echo '| ![](/img/2016/12/020.jakis-tam-text1.png#medium) | ![](/img/2016/12/021.jakis-tam-text2.png#medium) |' | sed -n 's#| !\[.*\](\(\/img\/\)\([0-9]*\/[0-9]*\/[0-9]*\)\.\(.*\)\.\(.*\)) |#| ![\3](\1\2.\3.\4) |#p'
| ![jakis-tam-text2](/img/2016/12/021.jakis-tam-text2.png#medium) |
And here's an example with three matches:
$ echo '| ![](/img/2016/12/020.jakis-tam-text1.png#medium) | ![](/img/2016/12/021.jakis-tam-text2.png#medium) | ![](/img/2016/12/022.jakis-tam-text3.png#medium) |' | sed -n 's#| !\[.*\](\(\/img\/\)\([0-9]*\/[0-9]*\/[0-9]*\)\.\(.*\)\.\(.*\)) |#| ![\3](\1\2.\3.\4) |#p'
| ![jakis-tam-text3](/img/2016/12/022.jakis-tam-text3.png#medium) |
Why does this happening?
Is there a way to force sed to print the result only for the very first match?
The expected behavior? I though the following command would print something similar to this (just the first match):
$ echo '| ![](/img/2016/12/020.jakis-tam-text1.png#medium) | ![](/img/2016/12/021.jakis-tam-text2.png#medium) | ![](/img/2016/12/022.jakis-tam-text3.png#medium) |' | sed -n 's#| !\[.*\](\(\/img\/\)\([0-9]*\/[0-9]*\/[0-9]*\)\.\(.*\)\.\(.*\)) |#| ![\3](\1\2.\3.\4) |#p'
| ![jakis-tam-text1](/img/2016/12/020.jakis-tam-text1.png#medium) |
or this (all matches):
$ echo '| ![](/img/2016/12/020.jakis-tam-text1.png#medium) | ![](/img/2016/12/021.jakis-tam-text2.png#medium) | ![](/img/2016/12/022.jakis-tam-text3.png#medium) |' | sed -n 's#| !\[.*\](\(\/img\/\)\([0-9]*\/[0-9]*\/[0-9]*\)\.\(.*\)\.\(.*\)) |#| ![\3](\1\2.\3.\4) |#p'
| ![jakis-tam-text1](/img/2016/12/020.jakis-tam-text1.png#medium) | ![jakis-tam-text2](/img/2016/12/021.jakis-tam-text2.png#medium) | ![jakis-tam-text3](/img/2016/12/022.jakis-tam-text3.png#medium) |

What's happening is that | !\[.*\] matches the longest possible match. That is, the first phrase, up to the beginning of the last phrase. If you want to match only the first phrase you must be more specific. For instance with:
sed 's#| !\[\]\(([^.]*\.\([^.]*\)\.[^)]*)\) |.*#| ![\2]\1 |#'

I do not fully understand the question, but, you can try this sed
$ sed 's#\([^[]*.\)\([^\.]*.\([^\.]*\)[^)]*.\)#\1\3\2#' input_file
This will print all 3 matches but will only substitute into the first match
$ sed 's#\([^[]*.\)\([^\.]*.\([^\.]*\)[^)]*.\)#\1\3\2#' input_file
| ![jakis-tam-text1](/img/2016/12/020.jakis-tam-text1.png#medium) | ![](/img/2016/12/021.jakis-tam-text2.png#medium) | ![](/img/2016/12/022.jakis-tam-text3.png#medium) |
To target all 3, the g flag can be added
sed 's#\([^[]*.\)\([^\.]*.\([^\.]*\)[^)]*.\)#\1\3\2#g' input_file
| ![jakis-tam-text1](/img/2016/12/020.jakis-tam-text1.png#medium) | ![jakis-tam-text2](/img/2016/12/021.jakis-tam-text2.png#medium) | ![jakis-tam-text3](/img/2016/12/022.jakis-tam-text3.png#medium) |
You could also target just #2 for example
$ sed 's#\([^[]*.\)\([^\.]*.\([^\.]*\)[^)]*.\)#\1\3\2#2' input_file
| ![](/img/2016/12/020.jakis-tam-text1.png#medium) | ![jakis-tam-text2](/img/2016/12/021.jakis-tam-text2.png#medium) | ![](/img/2016/12/022.jakis-tam-text3.png#medium) |

Related

How do i use \ (backslash) in a here-doc and have it show up when I print?

print <<EOTEXT;
(`-') (`-') _<-. (`-')_ <-. (`-')
_(OO ) ( OO).-/ \( OO) ) .-> \(OO )_
,--.(_/,-.\(,------.,--./ ,--/ (`-')----. ,--./ ,-.)
\ \ / (_/ | .---'| \ | | ( OO).-. '| `.' |
\ / / (| '--. | . '| |)( _) | | || |'.'| |
_ \ /_) | .--' | |\ | \| |)| || | | |
\-'\ / | `---.| | \ | ' '-' '| | | |
`-' `------'`--' `--' `-----' `--' `--'
EOTEXT
This is my ascii art that id like to show up in console. How ever it seems that " \ " doesnt show up. Is there a way that i can make it appear.
In double-quoted string literals, \ is the start of an escape sequence. When followed by a non-word character, it causes that character to be produced. For example, \| and \␠ produce | and a space respectively. And of course, \\ produces \, so we can use \\ where we want \ in double-quote string literals.
Here docs (<< string literals) act as double-quoted string literals, unless the token that follows the << is single-quoted. Then the string produced matches the input exactly.
So we have the option of prepending \ to every special character (\, $ and #), or we can simply single-quote the token.
print <<'EOTEXT';
(`-') (`-') _<-. (`-')_ <-. (`-')
_(OO ) ( OO).-/ \( OO) ) .-> \(OO )_
,--.(_/,-.\(,------.,--./ ,--/ (`-')----. ,--./ ,-.)
\ \ / (_/ | .---'| \ | | ( OO).-. '| `.' |
\ / / (| '--. | . '| |)( _) | | || |'.'| |
_ \ /_) | .--' | |\ | \| |)| || | | |
\-'\ / | `---.| | \ | ' '-' '| | | |
`-' `------'`--' `--' `-----' `--' `--'
EOTEXT

remove all characters in every line starting from the character "\" in a text file using powershell

I have 50 lines text file ($file1) like and i need to remove the characters starting from an specific character "/" until,the end of the line.
Sample text file:
| Area | vserver | file-id |connection-id | session-id | open-mode | path |
| manphsan01 | manphs101 | 9980 | 4278018043 | 5065142205921760710 | rw | Share01\Mandaue\Data01 |
| manphsan01 | manphs101 | 1790 | 4278020659 | 5065142205921763223 | rwd | FinanceDept\ARCHIVING |
| manphsan01 | manphs101 | 1824 | 4278020659 | 5065142205921763223 | rwd | Share01\Cebu\Year2022 |
| manphsan01 | manphs101 | 1976 | 4278020659 | 5065142205921763223 | rwd | SGSDept\General\Document |
My desired output sh0uld be like:
| Area | vserver | file-id |connection-id | session-id | open-mode | path |
| manphsan01 | manphs101 | 9980 | 4278018043 | 5065142205921760710 | rw | Share01 |
| manphsan01 | manphs101 | 1790 | 4278020659 | 5065142205921763223 | rwd | Finance |
| manphsan01 | manphs101 | 1824 | 4278020659 | 5065142205921763223 | rwd | Share01 |
| manphsan01 | manphs101 | 1976 | 4278020659 | 5065142205921763223 | rwd | SGSDept |
the command i used is like this:
$var = Get-content $file1
$var.Substring(0, $var.IndexOf('\')) | FT -AutoSize or
$var.Substring(0, $var.IndexOf('backslash')) | FT -AutoSize
My command will work if my data is only 1 line but multiple lines it wont work. I am not sure why the 'backslash' is not showing on the command when i posted it.
ny ideas how to make this work?
You can get away with plain-text processing if you can assume that only one field on each line of your structured text file contains \ and that it and everything after it - up until the next field delimiter, | - should be removed:
# Transforms all matching lines and outputs them.
# Pipe to Set-Content to save back to a file; use -Encoding as needed.
(Get-Content $file) -replace '\\.+?(?= \|)'
The above uses a -replace operation with a regex to remove the unwanted part of matching lines (lines that don't match are passed through as-is).
For an explanation of the regex and the ability to experiment with it, see this regex101.com page.
As for what you tried:
$var = Get-content $file1 stores the individual lines of file $file1 as an array in variable $var1.
To process the resulting lines one by one, you need a loop construct, such as a foreach statement or the ForEach-Object cmdlet; e.g. foreach ($line in $var) { ... }
While $line.Substring(0, $line.IndexOf('\')) works in principle, it will cause a statement-terminating error (exception) for every $line value that contains no \ character, as Theo notes, notably with your file's header line.
While this could easily be fixed with try { $line.Substring(0, $line.IndexOf('\')) } catch { $line }, the bigger problem is that it would remove everything through the end of the line, which contradicts your desired output, which shows that the next field seprator, | should be retained.
The above -replace operation fixes both these problems; note that it implicitly loops over the array of input lines and performs the replacement operation on each, returning an array of (potentially) transformed lines.
Also note that a formatting cmdlet such as Format-Table (-FT) should only be used for for-display output; it doesn't produce usable data - see this answer for more information; also, it has no formatting effect on strings.

escape pipe( | ) character inside table. in Github pages

In my github page, the escape charecters not working currectly.
https://alirezanet.github.io/Gridify/
but its working currectly in github
if i remove these backslashes from MD file entire table will break in github,
how can i fix this?
| Name | Operator | Usage example |
| --------------------- | -------- | --------------------------------------------------------- |
| Equal | `==` | `"FieldName==Value"` |
| AND - && | `,` | `"FirstName==Value , LastName==Value2"` |
| OR - \|\| | `\|` | `"FirstName==Value \| LastName==Value2"` |
| Parenthesis | `()` | `"( FirstName=*Jo,Age<<30) \| ( FirstName!=Hn,Age>>30 )"` |
You can use:
<code>|</code>
in replacement of |

Command line qustion

What is the difference between these two commands?
$ cat volcanoes.txt | wc > islands.txt
results:
$ cat islands.txt
17 26 204
second command:
$ cat volcanoes.txt | wc | cat > islands.txt
results:
$ cat islands.txt
17 26 204
We can see two results are same.
I am confused about the second commands.Why it has another cat in the commands.
Thank you for the help:)
The cat command just copies its input to its output verbatim.
So even
cat volcanoes.txt | cat | cat | wc | cat | cat | cat | cat > islands.txt
would lead to the same content of islands.txt.
Even without cat you can get the same result:
wc < volcanoes.txt > islands.txt
This one being the most efficient version, starting only one process.

org-babel not concatenating strings before sending to code block variable.

I have just started using org-mode and org-babel as a lab notebook. I am trying to use a code block to fill in two columns of a table. The code block seems to work for the first column because those are the right numbers. However, when trying to concatenate a string to the file name in column three so the code blocks works on a different set of files it seems to just run the code block on the original files instead, which produces the same output as column one.
#+name: tRNAs
#+begin_src sh :var filename="" :results silent
cd Data/tRNA
grep -c ">" $filename
#+end_src
#+tblname: sequences
| # of Sequences before QC | # after QC | Original File name|
|--------------------------+------------+------------------|
| 681865 | 681865 | read1 |
| 324223 | 324223 | read2 |
| 1014578 | 1014578 | read3 |
| 971965 | 971965 | read4 |
| 931777 | 931777 | read5 |
| 810798 | 810798 | read6 |
| 965134 | 965134 | read7 |
| 718474 | 718474 | read8 |
|--------------------------+------------+------------------|
#+TBLFM: $1='(org-sbe tRNAs (filename (concat "\"" $3 "\"")))
#+TBLFM: $2='(org-sbe tRNAs (filename (concat "\"final_" $3 "\"")))