I'm trying to insert a line in a file after it matched the regex for the last time.
It's actually adding the line but at the end of the file.
tasks:
- name: add to ansible hosts file
lineinfile:
dest: "hosts"
insertafter: '^\[ansible_ssh_host\]'
line: " test ansible_ssh_host=172.0.0.3"
I want it to be added after the last line containing "ansible_ssh_host"
Destination file
ansible-server ansible_ssh_host=172.0.0.1
template-server ansible_ssh_host=172.0.0.2
[tag_ansible-servers]
ansible-server
[tag_template-servers]
template-server
'^\[ansible_ssh_host\]' means search for a line that begins with [ansible_ssh_hosts], but none of your lines actually start with that. You need a regexp which matches anywhere in the line.
Try this:
- name: add to ansible hosts file
lineinfile:
dest: "hosts"
insertafter: 'ansible_ssh_host='
line: " test ansible_ssh_host=172.0.0.3"
Related
Currently when I change the version number in my project I have to define it in my build.gradle file and several places in my bitbucket-pipelines.yml. This is because I have scripts to upload files to my project's Downloads folder. Is there a way to get the version from the build.gradle file? I would like to just update one file when I increment the version.
build.gradle
plugins {
id 'java'
}
def buildNumber = project.properties['buildNumber'] ?:'0'
group 'edu.csusb.iset'
version "2020.1-BETA"
jar {
manifest {
attributes('Main-Class': 'edu.csusb.iset.projectname.Main',
'Implementation-Title': 'ProjectName',
'Implementation-Version': "$version, build $buildNumber")
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
task packSrc(type: Tar) {
archiveAppendix.set("src")
archiveVersion.set("$project.version")
archiveExtension.set("tar.gz")
destinationDirectory = file("$buildDir/dist")
compression = Compression.GZIP
from 'build.gradle'
from 'settings.gradle'
from('src') {
include '**/*'
into "src"
}
}
repositories {
mavenCentral()
}
dependencies {
...
}
bitbucket-pipelines.yml
image: openjdk:11
pipelines:
default:
- step:
name: Gradle build
caches:
- gradle
script:
- bash ./gradlew build
- step:
name: Deploy downloads
trigger: manual
caches:
- gradle
script:
- bash ./gradlew build
- pipe: atlassian/bitbucket-upload-file:0.1.6
variables:
BITBUCKET_USERNAME: $BITBUCKET_USERNAME
BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD
FILENAME: build/libs/ProjectName-2020.1-BETA.jar
- bash ./gradlew packSrc
- pipe: atlassian/bitbucket-upload-file:0.1.6
variables:
BITBUCKET_USERNAME: $BITBUCKET_USERNAME
BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD
FILENAME: build/dist/ProjectName-src-2020.1-BETA.tar.gz
Bitbucket Pipelines is just running bash/shell commands on a Unix docker machine. So you can use the normal unix shell commands, like awk or perl, to extract text from a text file:
Use awk
build.gradle contains a line:
version "2020.1-BETA"
awk '/^version/{gsub(/\"/,"",$2);print $2}' build.gradle
Output: 2020.1-BETA
Explanation:
awk = extract text on a line, using the default space character " " as a delimiter
^ = Regular expression to start at the beginning of a line only
version = Look for the word "version", case-sensitive
{gsub(/\"/,"",$2);print $2} = strip out all speech mark characters ", and print column 2
More info and source: how to extract text which matches particular fields in text file using linux commands
Another way with perl
build.gradle contains a line:
version "2020.1-BETA"
perl -nle 'print $& while m{(?<=version ").*?(?=")}g' build.gradle
Output: 2020.1-BETA
Explanation:
Extract the text between two words of: version " and ", using a regular expression
perl -nle = extract text from a line in a file, using regular expressions
(?<=version ") = Look for the start tag of version ", using negative lookahead ?<= to make the capture start at the end of the tag
.*? = Capture any string, after the first tag
(?=") = Look for the end tag of a speech mark ", using positive lookahead ?= to make the capture stop before the tag
g = global search on all lines of a multi-line file
More info and sources: grep -P no longer works. How can I rewrite my searches? and How to use sed/grep to extract text between two words?
Use the shell commands in the yml script
You can therefore use either awk or perl in your yml script. Capture the output as an environment variable called $APP_VERSION, and reuse this environment variable:
script:
- bash ./gradlew build
# Extract the version string from build.gradle into an environment variable
- export APP_VERSION=$(awk '/^version/{gsub(/\"/,"",$2);print $2}' build.gradle)
- echo $APP_VERSION # debug to print the extracted text of "2020.1-BETA"
- pipe: atlassian/bitbucket-upload-file:0.1.6
variables:
BITBUCKET_USERNAME: $BITBUCKET_USERNAME
BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD
FILENAME: "build/libs/ProjectName-$APP_VERSION.jar" # Use the extracted text here
Alternative way:
script:
- bash ./gradlew build
# Extract the version string from build.gradle into an environment variable
- export APP_VERSION=$( perl -nle 'print $& while m{(?<=version ").*?(?=")}g' build.gradle )
- echo $APP_VERSION # debug to print the extracted text of "2020.1-BETA"
- pipe: atlassian/bitbucket-upload-file:0.1.6
variables:
BITBUCKET_USERNAME: $BITBUCKET_USERNAME
BITBUCKET_APP_PASSWORD: $BITBUCKET_APP_PASSWORD
FILENAME: "build/libs/ProjectName-${APP_VERSION}.jar" # Use the extracted text here
I am using ansible v2.2.1 and I need to remove only the first occurrence of a line in file. So my ansible playbook is as follows.
---
- hosts: localhost
tasks:
- name: read file content
command: cat occurence.txt
register: fc
- debug: var=fc
- debug: msg="{{ item }}"
with_items:
- "{{ fc.stdout_lines }}"
- name: first occurence in file
shell: sed -i '0,/{{ item }}/{/{{ item }}/d;}' occurence.txt
with_items:
- "{{ fc.stdout_lines }}"
register: remove
- debug: var=remove
And occurence.txt file has following content
this is apple
this is apple
this is banana
this is apple
this is orange
How can I delete only the first occurrence of line "this is apple" and leave rest of the lines?
I'm liking Yunnosch's interpretation of the question. An alternative would be this:
sed '0,/^this is apple$/{//d}'
From the beginning of the file to the first occurrence of the apple line, delete only lines matching the previous match.
Find line, when found replace by (initially empty) hold space.
For later occurences, swapping to the identical hold space will basically print unchanged line, even if it, strictly speaking, it is the previous identical line.
Delete in case of (only the first) empty line coming from hold space.
sed "/^this is apple$/{x;/^$/d}"
I solved it as follows by using set_fact variable.
---
- hosts: localhost
tasks:
- name: read file content
command: cat occurence.txt
register: fc
- debug: var=fc
- debug: msg="{{ item }}"
with_items:
- "{{ fc.stdout_lines }}"
- set_fact: value="this is apple"
- debug: var=value
- name: first occurrence in file
shell: sed -i '0,/{{ value }}/{/{{ value }}/d;}' occurence.txt
register: remove
- debug: var=remove
I am using [file lookup] which reads the whole file and stores the content in a variable. My play looks something like this:
- name: Store foo.xml contents in a variable
set_fact:
foo_content: "{{ lookup('file', 'foo.xml' ) | replace('\n', '')}}"
So the above code reads the foo.xml file and stores it in the variable, but the problem is when the foo.xml has line breaks in it, it also includes the line break in the variable.
My foo.xml is this file:
<?xml version="1.0" encoding="utf-8"?>
<initialize_param>
<secrets>
<my_secret id="99">3VMjII6Hw+pd1zHV5THSI712y421USUS8124487128745812sajfhsakjfasbfvcasvnjasjkvbhasdfasgfsfaj5G8A9+n8CkLxk7Dqu0G8Jclg0eb1A5xeFzR3rrJHrb2GBBa7PJNVx8tFJP3AtF6ek/F/WvlBIs2leX2fq+/bGryKlySuFmbcwBsThmPJC5Z5AwPJgGZx</my_secret>
</secrets>
</initialize_param>
The output removes line break \n but also incudes the tabs \r & \t
I need to got rid of the \n , need to get rid of extra formatting too (\r & \t), Moreover after the replace filter I get the error while firing a DB Update query as
stderr: /bin/sh: 1: cannot open ?xml: No such file
Use the Jinja trim filter:
"{{ lookup('file', 'foo.xml' ) | trim }}"
You can do that with the replace filter?
contents: "{{ lookup('file', '/etc/foo.txt') | replace('\n', '')}}"
You may use the regex_replace filter since the trim doesn't clear other line break characters as you mentioned in the question.
"{{ some_stdout_to_clear | regex_replace('[\\r\\n\\t]+','') }}"
I am new in scripting and need help on this one: I have a .txt file; in each line I have digits, for example:
123456
234567
345678
567890
....
On the other hand, in a master directory I have subdirectories. In each subdirectory, I have a file in .xml format. In each of the .xml files I have one tag with 6 digits; example: in file 1.xml under sub directory 1, the tag value is 123456, in file 2.xml under sub directory 2, the tag value is 111111, in file 3.xml under sub directory 3, the tag value is 345678, ...
How can I extract the list of subdirectories and save to a file where there is a match in digits between .txt file and .xml files? Thanks
I was able to save in an output file lines in the xml file under sub directories having the string that I am searching for using the command line:
grep -r HDContent Priorite_2_HD/*/adi_new.xml
where Priorit_2_HD is the sub directory and adi_new.xml is the .xml file
The output looks like
Priorite_2_HD/ados_contre_attaquent_les_hd_vf_Ingest/adi_new.xml:
Priorite_2_HD/Ainsi_Soient_Ils_Saison_1_vf_W/adi_new.xml:
Priorite_2_HD/Ainsi_Soient_Ils_Serie_vf_W/adi_new.xml:
Priorite_2_HD/Amour_Haine_Propagande_Saison_1_vf_W/adi_new.xml:
Priorite_2_HD/Amour_Haine_Propagande_Saison_2_vf_W/adi_new.xml:
Priorite_2_HD/Amour_Haine_Propagande_Serie_vf_W/adi_new.xml:
Priorite_2_HD/Apparences_Saison_1_vf_W/adi_new.xml:
Priorite_2_HD/Apparences_Serie_vf_W/adi_new.xml:
Priorite_2_HD/Arthur_Saison_11_vf_W/adi_new.xml:
Now using awk i want to put in an output file all lines having the string HDContent="Y". trying to use the command line
awk 'BEGIN { FS = "/" } ; { if $3== "Value="\Y\""; print $2, $3}' input.txt
but no luck . Thanks
I'm looking for a pattern in a file which looks like below. In this example, I need to grep for a string mgrpRFC822MailMember: foo.foo2#example.com
If the above string matches then go up and find the first dn: line and print
test-d#example.com
Now, the issue is, the line dn: is not always at the same number (In the below example the line dn: is 3 lines above the grep'ed line mgrpRFC822MailMember: foo.foo2#example.com)
This not always true. It can be on any number before the mgrpRFC822MailMember: foo.foo2#example.com
Here is the condition:
grep for the string - mgrpRFC822MailMember: foo.foo2#example.com
If matches, look for the FIRST dn: line above this line and only print test-d#example.com
Any help is greatly appreciated.
time: 1364633264
dn: mailRoutingAddress=test-d#example.com,ou=MessageRecipientGroups,dc=example,dc=com
changetype: modify
delete: mgrpRFC822MailMember
mgrpRFC822MailMember: foo.foo2#example.com
-
replace: entryCSN
entryCSN: 20130330084739Z#00000b#00#000000
-
replace: modifiersName
modifiersName: uid=distlist-cleanup,ou=SysAccounts,dc=example,dc=com
You can also use sed which may be faster. Put the following into a file, say x.sed, do not add any spaces or tabs
/dn:/h
/MailMember:/{
g
s/.*RoutingAddress.//
s/,.*//p
}
Then run sed like this
sed -n -f x.sed filename
For your example, it prints out
test-d#example.com
awk '/dn: /{bar=$2} /MailMember:/{print bar}' FS='[=,]'
look for dn: line
save line as bar variable
look for MailMember: line
print bar variable