Multi-paragraph attribute in AsciiDoc - asciidoc

I have a two-paragraph text that gets repeated fairly often. How could I avoid the repetition?
For now I have:
:something-1: Blah blah blah +
blah blah blah +
blah blah blah
:something-2: Blah blah blah +
blah blah blah +
blah blah blah
And then:
--
{something-1}
{something-2}
--
Is there a way I could put both paragraphs into one attribute? It would be even better if I could put the block into the attribute too.
This doesn't work:
:something: Blah blah blah +
blah blah blah +
blah blah blah +
+
Blah blah blah +
blah blah blah +
blah blah blah
The plus on the empty line and the second paragraph are not parsed as part of the attribute definition.
Another option is putting the two paragraphs in a separate file and using the include: macro. But creating a separate file every time I face this problem would create some clutter. It also makes it harder than necessary to go from 1-paragraph definitions to 2-paragraph definitions. I'd rather have a single "glossary" section (or document) which contains all these repeated term definitions.

I don't know if multi-paragraph attributes are possible, but selective imports definitely are! I now have a glossary.asciidoc file:
tag::something[]
--
Blah blah blah
Blah blah blah
--
end::something[]
And I can import this section by saying:
include::glossary.asciidoc[tag=something]
A major advantage of this approach is that text formatting inside the snippet works.

Related

How to use :put to append a variable at the end of the current line with vim

I have the following command, which I need to insert in a bash script:
vim file.txt -c ':let var=$foo' -c ':execute "normal! gg/string\<cr>V"' -c ":normal! d" -c ':execute "normal inewstring\<Esc>"' -c ':put =var'
What it does (or what I want it to do) is to use the variable foo, which is defined on the script, search for the first appearance of string select the whole line and delete it, then insert newstring and append the value of foo just after this new string. However, my code puts the value always in the next line, no matter if I change the x value in :[x]put.
As a novice in vim I'm not sure even if this way to achieve my goal is efficient, so any suggestion is welcome. Thanks in advance.
Let's say that we have this input file:
$ cat file.txt
blah
string foo
string foo
blah
What I'm expecting to obtain (defining $foo="hello") is:
$ cat file.txt
blah
newstringhello
string foo
blah
I am a big vim fan, but if I were you, I won't do it with vim.
Since you didn't post the example input the desired output, I can only guess what do you want from your description.
Given that we have:
kent$ cat f
blah
string foo bar
string foo bar
blah
And var="hello", the next sed one-liner changes the input file into:
kent$ sed "0,/string/{/string/s/.*/newString/};$ a \\$var" f
blah
newString
string foo bar
blah
hello
However I don't know if it is exactly what you wanted.
update
kent$ sed "0,/string/{/string/s/.*/newString$var/}" f
blah
newStringhello
string foo bar
blah

Special characters in Salt state

I am using Salt and I have to append some text to a file,after some research I found that you can achieve that by using the file.append module.
I am getting an error about adding something like [text] in the file:
failed: could not found expected ':';at line x
The state is:
file.append:
- text: |
blah blah blah
[SSL] <====================== Here is where it complains
blah blah
Should I try to escape the [ character using the \ before or how am I able to do that?
The problem is your indentation. A mapping value must be indented more than its key:
file.append:
- text: |
blah blah blah
[SSL]
blah blah

Matching across a line vs matching words regex

Why is it that when I match across new lines it would seem that I can't identify individual words. For example:
content = "COAL_STORIES
AUSTRALIA - blah blah blah
BOTSWANA – blah blah blah
URANIUM_STORIES
AUSTRALIA – blah
INDIA - blah
COPPER_STORIES
AUSTRALIA - blah blah blah
AUSTRALIA - blah blah blah
CHINA - blah blah blah
ALUMINIUM_STORIES"
sections = content.scan(/\w.*_.*\b/)
Give and array:
[
[0] "COAL_STORIES",
[1] "URANIUM_STORIES",
[2] "COPPER_STORIES",
[3] "ALUMINIUM_STORIES"
]
But if I try that using the 'm' flag everything gets matched:
sections = content.scan(/\w.*_.*\b/m) gives an array:
[
[0] "COAL_STORIES\nAUSTRALIA - blah blah blah\nBOTSWANA – blah blah blah \n\nURANIUM_STORIES \nAUSTRALIA – blah\nINDIA - blah\n\nCOPPER_STORIES\nAUSTRALIA - blah blah blah\nAUSTRALIA - blah blah blah\nCHINA - blah blah blah\n\nALUMINIUM_STORIES"
]
As far as I can tell I'm still looking for the same word boundaries?
To elaborate on Casimir's comment:
.* is greedy... it will match the longest possible string it can, including newlines if you let it (which you can/did do by enabling multiline matching with \m).
In your first example .* will not match newlines, so \b is forced to match a word boundary on the same line as where \w matched.
In your second example .* will match across lines, so when \w matches your first character, \b is free to match any word boundary, even many lines away, as long as there's an _ somewhere between the two. Specifically, for you, it looks like:
\w matched the first character in your input: "C" from "COAL_STORIES"
.* matched everything up to "ALUMINUM" on the last line
_ matched "_"
.* matched "STORIES"
\b matched the end of "STORIES"

Use SED to delete all lines between a single repeating pattern

I'd like to use sed to delete all lines between a pattern that repeats throughout a text file.
Input
SET ENG_1
blah blah
blah blah
SET ENG_2
blah blah
blah blah
SET TEST
blah blah
blah blah
SET ENG_5
blah blah
blah blah
SET OPEN
blah blah
blah blah
SET ENG_10
blah blah
blah blah
There are multiple SET ENG_# lines, but I never know what the number on the end will be. I want to remove all lines between SET ENG_ and the next line that starts with SET.
Desired output
SET ENG_1
SET ENG_2
SET TEST
blah blah
blah blah
SET ENG_5
SET OPEN
blah blah
blah blah
SET ENG_10
I would like to edit the file in place, like using the -i option in sed.
My attempt
Here is what I have tried:
sed -i "/SET ENG_/,/SET ENG_/{//!d}" $MYFILE
It only works on the first occurrence, so I get this output:
SET ENG_1
SET ENG_2
blah, blah
blah blah
How can I change my approach to obtain my desired output?
This might work for you (GNU sed):
sed -r '/SET/!b;:a;$!{N;ba};s/((SET)[^\n]*\n).*\n([^\n]*\2)/\1\3/' file
This will retain the first and last patterns (in your case SET).
This alternative will remove the first and last patterns as well:
sed -r '/SET/!b;:a;$!{N;ba};s/[^\n]*(SET).*\1[^\n]*\n?//' file
On reading the amendment to you question, perhaps this might work for you:
sed -ni ':a;/^SET ENG_[1-9]/{p;:b;$q;n;/^SET/ba;bb};p' file
If you have some text like this:
cat file
start text
SET ENG_1
blah blah
blah blah
SET ENG_2
blah blah
blah blah
SET ENG_3
blah blah
blah blah
SET ENG_4
end text
blah blah
blah blah
This will then print all data before first SET ENG and after last SET ENG:
awk '/SET ENG/ {e=NR;if (!f) f=NR} {a[NR]=$0} END {for (i=1;i<=NR;i++) if (f>i||i>e) print a[i]}' file
start text
end text
blah blah
blah blah
Using awk with custom record separator you can use:
awk -v RS= '{sub(/SET ENG.*SET ENG[^\n]*\n/, "")} 1' file
start text
end text
blah blah
blah blah
This example is using same sample data as in Jotne's answer.
It looks from your question like this is all you need:
$ grep 'SET ENG_' file
SET ENG_1
SET ENG_2
If that's not what you wanted, edit your question to clarify your requirements, provide more truly representative input and the precise expected output given that input.
Based on your new desired output, I would interpret what you're trying to do as this:
If /SET ENG/ matches, switch off output
If /SET [anything else]/ switch it back on
Print all SET lines
This script does that:
$ awk '/SET/ { if (/ENG/) { print; f = 0 } else f = 1 } f' file
SET ENG_1
SET ENG_2
SET TEST
blah blah
blah blah
SET ENG_5
SET OPEN
blah blah
blah blah
SET ENG_10

Append line only when 2 search criteria are met

I want to accomplish the following with sed
1.Find first occurrence of [sometext] Exact match
2.Then start search from there for stuID = 10 Exact match
3.Then append line checkID = 4 for the first occurance of stuID under [sometext]
Note : the value of checkID will change according to [sometext] that's why i need to append line for first occurance only
My attempts
sed '/[sometext]/{ s/stuID = 10/a\checkID = 4/1 }' file.txt
sed 's/[sometext]/{ s/stuID = 10/a\checkID = 4/1 }' file.txt
sed '/[sometext]/{ s/stuID = 10/a\checkID = 4/g }' file.txt
{just to see if command works if i don't specify the number of times to add new line.
I added \ ] to escape []
Results
1.Command get executed but checkID=4 is not added anywhere in file.txt
2.Error : sed: -e expression #1, char 18: multiple g' options to s' command
Implying that syntax itself is wrong
3.Command get executed but checkID=4 is not added anywhere in file.txt
When i say executed i mean there is no error message
File.txt
[sometext]
blah blah blah
blah blah blah
stuID = 10
blah blah blah
blah blah blah
[Anothertext]
blah blah blah
blah blah blah
stuID = 5
blah blah blah
blah blah blah
I want it to be
File.txt
[sometext]
blah blah blah
blah blah blah
stuID = 10
checkID=4
blah blah blah
blah blah blah
[Anothertext]
blah blah blah
blah blah blah
stuID = 5
checkID=6
blah blah blah
blah blah blah
I am completely tired and clueless at this point .Hope someone can help me out
Regards
This might work for you (GNU sed):
sed -e '/\[sometext\]/,/stuID = 10/{/stuID = 10/{a\checkID = 4' -e ':a;n;ba}}' file
This finds the range between the 2 search strings and appends the desired text. Finally the rest of the file is passed over.

Resources