sed conditional branching with multiline section - sed

I'm trying multiline replacement with sed for the first time. I found a couple of good pointers out there (general multiline help and multiline between two strings). Using this as a starter, I have the following command:
sed '
/<dependency>/,/<\/dependency>/ { # Find a set of lines for a dependency
s/\(<artifactId>\)m[^<]*\(<\/artifactId>\)/\1ARTIFACTID\2/ # Substitute if artifactId starts with 'm'
t depend-update # If we substituted, go to depend-update. Otherwise, continue
:depend-unchanged
s/\(<groupId>\)[^<]*\(<\/groupId>\)/\1CHANGE_A\2/ # Change groupId to have 'A'
b # branch to end
:depend-update
s/\(<groupId>\)[^<]*\(<\/groupId>\)/\1CHANGE_B\2/ # Change groupID to have 'B'
b # branch to end
}
' \
inputfile.xml
My input file has the following contents:
<dependency>
<groupId>foo</groupId>
<artifactId>test.a</artifactId>
</dependency>
<dependency>
<groupId>bar</groupId>
<artifactId>mytest.a</artifactId>
</dependency>
<dependency>
<groupId>baz</groupId>
<artifactId>test.b</artifactId>
</dependency>
Unfortunately, for all sections, I get "CHANGE_A". As I understand it, this means that sed always thinks that the first replace did nothing, even though it did. The result is:
<dependency>
<groupId>CHANGE_A</groupId>
<artifactId>test.a</artifactId>
</dependency>
<dependency>
<groupId>CHANGE_A</groupId>
<artifactId>ARTIFACTID</artifactId>
</dependency>
<dependency>
<groupId>CHANGE_A</groupId>
<artifactId>test.b</artifactId>
</dependency>
Where did I go wrong?

Multi line is due to the "problem" that sed work line by line on a strem/file input and not as a whole.
In your case you treat a pack of line but still 1 line at a time and not as a block
/startBlock/,/EndBlock/ mean just, treat all line inside those 2 delimiter, not group the block in 1 big block
Here is the adaptation proposed
sed '
/<dependency>/,\#</dependency># {
# load into the buffer
/<dependency>/ h;/<dependency>/ !H
\#</dependency># {
# At end of block, load the buffer and work on it
g
# Find a set of lines for a dependency
s/\(<artifactId>\)m[^<]*\(<\/artifactId>\)/\1ARTIFACTID\2/ # Substitute if artifactId starts with 'm'
t depend-update # If we substituted, go to depend-update. Otherwise, continue
:depend-unchanged
s/\(<groupId>\)[^<]*\(<\/groupId>\)/\1CHANGE_A\2/ # Change groupId to have 'A'
# branch to end
b # branch to end
:depend-update
s/\(<groupId>\)[^<]*\(<\/groupId>\)/\1CHANGE_B\2/ # Change groupID to have 'B'
# branch to end
b
}
}
' \
inputfile.xml

Related

Apache Commons CLI: prevent repeated options & force exactly one argument?

I am using commons-cli 1.5.0. Let's say my command line syntax is the following:
Process -src <input> -dst <output>
My program ("Process") should accept exactly one -src and exactly one -dst.
However, DefaultParser allows such command lines as:
Process -src aaa.txt -src bbb.txt -src ccc.txt -dst result.txt
For the above line, getOptionValue("src") returns "aaa.txt", but getOptionValues("src") returns all 3 filenames.
Now, is there an option to disallow such syntax? To define that there can only be one -src, and if there are more, DefaultParser.parse() should throw an exception?
I've tried .hasArgs().numberOfArgs(1) and .hasArg().numberOfArgs(1),
but it did not seem to change anything...
You probably need to do this check yourself and fail the app yourself after parsing, e.g.
CommandLine cmd = parser.parse(options, args);
if (cmd.getOptionValues("src").length > 1) {
throw new IllegalStateException("Cannot handle more than one 'src' argument");
}

python-language-server config file location

I'm trying to use flake8 as the default python linter using python-language-server on neovim v0.5.
python-lsp documentation says to set pylsp.configurationSources to ['flake8'], but doesn't specify which file to edit.
Where does the python-lsp-server config file reside?
According to flake8 documentation, the location of flake8 config varies based on systems, on Linux and Mac, it is ~/.config/flake8, and for Windows, it is $HOME\.flake8 ($HOME is like C:\\Users\sigmavirus24). The content should be in INI format:
[flake8]
max-line-length = 100
max-complexity = 30
ignore =
# missing whitespace around arithmetic operator
E226,
# line break before/after binary operator
W503,
W504,
# expected 1 blank line, found 0
E301,E302,
To suppress a single warning, it is also handy to add # noqa: F841-like (change the code to the actual code you want to use) comment string to suppress it.
Ref: https://jdhao.github.io/2020/11/05/pyls_flake8_setup/#config-location

How to pass multiple arguments to dotCover merge

I am writing powershell command to merge two snapshots as following -
&$coveragTool merge /Source= $TestResult1;$TestResult2 /Output= TestMergeOutput.dcvr
it is giving error as -
Parameter 'Source' has invalid value.
Invalid volume separator char ':' (0x3A) in path at index 67.
where as the document says two files should be separated by a semicolon(;)
like this -
merge: Merge several coverage snapshots
usage: dotCover merge|m <parameters>
Valid parameters:
--Source=ARG : (Required) List of snapshots separated with semicolon (;)
--Output=ARG : (Required) File name for the merged snapshot
--TempDir=ARG : (Optional) Directory for the auxiliary files. Set to system temp by default
Global parameters:
--LogFile=ARG : (Optional) Enables logging and allows specifying a log file name
--UseEnvVarsInPaths=ARG : (Optional) [True|False] Allows using environment variables (for example, %TEMP%) in paths. True
by default
how do i make it correct?
You cannot pass an unquoted ; as part of an argument, because PowerShell interprets it as a statement separator.
Either enclose the argument in "...", or `-escape the ; character selectively; also, the space after = may or may not be a problem.
To make the call (at least syntactically) succeed, use the following:
& $coveragTool merge /Source="$TestResult1;$TestResult2" /Output=TestMergeOutput.dcvr
Alternatively (note the `, ignore the broken syntax highlighting):
& $coveragTool merge /Source=$TestResult1`;$TestResult2 /Output=TestMergeOutput.dcvr
PowerShell has more so-called metacharacters than cmd.exe, for instance, notably ( ) , { } ; # $ # in addition to & | < > - see this answer for additional information.

Using sed, delete from specific line until first match(not included)

I have some data looks like
1:Alice 2313
2:Desctop 456
3:Cook 111
4:.filename 50
...
...
100:Good 3
Dir num:10
File num:90
...
...
I want to delete all lines from specific line(ex. line 3) until the line "Dir num:" show up.
The idea output should be(according above example):
1:Alice 2313
2:Desctop 456
Dir num:10
File num:90
...
...
I have google several solutions likesed -i '/somestring/,$!d' file.
But these solutions are not suitable because of the specific line where deletion satarting.
How can I do this in 1 command without any tmp file?
Forgive my poor English, I'm not native English speaker.
You need to specify the address range from the specified line number (3) to the line matching the pattern (/Dir num/). However, it's not quite as simple as
sed '3,/Dir num/ d' file
because that will delete the "Dir num" line. Try this instead:
sed '3,/Dir num/ {/Dir num/! d}' file
That will, for the lines in the range, check that the line does not match the pattern: is the pattern is not matched, delete it.
Use the range: /pattern1/,/pattern2/ option of sed
$ sed -e '/2:Desctop 456/,/Dir num:10/{//!d}' inputFile
1:Alice 2313
2:Desctop 456
Dir num:10
File num:90
...
...

In Bazaar (bzr), How to show log of only commits which were done in a specific branch nick?

In Mercurial (hg), a user can enter the following command --
hg log --branch branchName
This shows only the commits which were done against a specific named branch.
What bzr command can give me the same functionality? I could not find an option for "bzr log" that would do the same thing. For example, if I committed revs 1, 2, and 3 in branch nick "trunk" and 2.1.1, 2.1.2, and 4 in branch nick "ftr-foo", how can I print only the revs under branch nick "ftr-foo" such that I'd only see 2.1.1, 2.1.2, 4? And how would I get only the commits which were done against the "trunk" branch nick such that I'd only see 1, 2, and 3?
DAG graph below.
4 [ftr-foo]
| \
3 \ [trunk]
| \
| 2.1.2 [ftr-foo]
| |
| 2.1.1 [ftr-foo]
| /
| /
2 [trunk]
|
1 [trunk]
While Bzr has the basic machinery to allow matching commits by other criteria, this is still a non-trivial exercise in plugin writing. A simpler alternative is to filter the output of bzr log or bzr log -n0 through a grep-like program that understands where commits begin and end.
The following Python program (which should work with both Python 2.7 and Python 3.x) allows you to grep bzr log output for arbitrary regular expressions:
#!/usr/bin/env python
import sys, re, os
args = sys.argv[1:]
if not args or args in [["--help"], ["-h"], ["-help"]]:
prog = os.path.basename(sys.argv[0])
print("Usage: bzr log BZRARGS | " + prog + " REGEX ...")
sys.exit(1)
patterns = [re.compile(pat) for pat in args]
def handle(block):
match = False
for line in block:
for pattern in patterns:
if re.search(pattern, line):
match = True
break
if match:
break
if match:
try:
for line in block:
sys.stdout.write(line)
except IOError:
sys.exit(0)
def main():
sep = "^\s*------------------------------------------------------------$"
sep = re.compile(sep)
stdin = sys.stdin
block = []
while True:
line = stdin.readline()
if not line:
if block:
handle(block)
break
if re.match(sep, line):
if not block:
block.append(line)
else:
handle(block)
block = [ line ]
else:
block.append(line)
main()
If you call this program bzr-greplog, you can then do:
bzr log -n0 | bzr-greplog 'branch nick: foo'
to search for branches with the nick foo. Note that the pattern will match anywhere within a line, so it will match a nick of foobar also, for example, or a commit message that happens to have this pattern. In order to avoid (most) such false positives, use an anchored regex instead, e.g. '^\s*branch nick: foo$' (the \s* is necessary because indented commits may begin with spaces). You can also use a script that allows you to search specifically for a branch nick:
#!/bin/sh
bzr log -n0 | bzr-greplog '^\s*branch nick: '"$1"'$'
Known bug: If a commit message contains exactly a bzr log record separator (with the exact same number of dashes), then bzr-greplog will misinterpret the commit as two commits and may leave out the part following the separator.