How to get a specific line based on a pattern if found - sed

I am trying to gather the filenames from a very big file depending on if a particular user, in this case windowsdom\nasarchive is found.
I tried running sed -nr "/-{3,}/h; /Path\s*:/H; /windowsdom\\nasarchive\s+Allow\s+FullControl/{x;G;p}" logfilename but it does not bring anything.
-----------------------
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - April 21 - 2.doc
AccessToString : windowsdom\nasarchive Allow FullControl
BUILTIN\Administrators Allow FullControl
NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Users Allow ReadAndExecute, Synchronize
-----------------------
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2009\Credit status - Sept. 23 - 59.doc
AccessToString : windowsdom\acl_1 Allow ReadAndExecute, Synchronize
windowsdom\acl_2 Allow Modify, Synchronize
windowsdom\acl_3 Allow ReadAndExecute, Synchronize
windowsdom\adm_server Allow Modify, Synchronize
BUILTIN\Administrators Allow FullControl
-----------------------
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - August 10 - 3.doc
AccessToString : windowsdom\nasarchive Allow FullControl
BUILTIN\Administrators Allow FullControl
NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Users Allow ReadAndExecute, Synchronize
-----------------------
Expected result:
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - April 21 - 2.doc
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - August 10 - 3.doc
Can someone think how to get the expected result?

Edit: I know it's not the best idea to edit an accepted answer, but it was substantially inaccurate. It turns out that the hold space is retained between lines.
The main problem with your command is that you are using double quotes, so the escaped backslash is seen unescaped by sed. Change them to single quotes and it starts working:
$ sed -nr '/-{3,}/h; /Path\s*:/H; /windowsdom\\nasarchive\s+Allow\s+FullControl/{x;G;p}' file
-----------------------
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - April 21 - 2.doc
AccessToString : windowsdom\nasarchive Allow FullControl
-----------------------
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - August 10 - 3.doc
AccessToString : windowsdom\nasarchive Allow FullControl
Now, you can simplify it to match the desired output. What you'll eventually get is shown in protong's answer:
sed -rn '/^Path:/h;/windowsdom\\nasarchive\s+Allow\s+FullControl/{g;p}' file
POSIX alternative:
$ sed --posix -n '/^Path:/h;/windowsdom\\nasarchive[[:space:]]\{1,\}Allow[[:space:]]\{1,\}FullControl/{g;p}' log.txt
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - April 21 - 2.doc
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - August 10 - 3.doc

This might work for you (GNU sed):
sed -rn '/^Path:/h;/windowsdom\\nasarchive\s+Allow\s+FullControl/{g;p}' file
This prints the last Path string when it encounters the required string.

Try with awk. You can save each line with the path and print it when found a line which first field matches AccessToString and the third one matches windowsdom\nasarchive:
awk '
$1 ~ /^Path/ { path = $0; next }
$1 ~ /^AccessToString/ && $3 ~ /^windowsdom\\nasarchive$/ { print path }
' infile
It yields;:
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - April 21 - 2.doc
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - August 10 - 3.doc

If you have gawk1 you can define a record as the text between lines of dashes with RS="-----------------------" and each field to be a line by setting FS="\n":
gawk '
BEGIN {RS="-----------------------"; FS="\n"}
$5 ~ /windowsdom\\nasarchive\s+Allow\s+FullControl/ {print $2;}
' ur_file.txt
Prints:
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - April 21 - 2.doc
Path: U:\Credit share\BI-WEEKLY CREDIT NOTES\2010\Credit status - August 10 - 3.doc
1To find out the version of awk, use awk --version. It is typical for linux to have gawk and have that linked to awk. OS X does not have gawk but it is easily installed.

Related

How to set correct file permissions with CGI::Session

For anyone else reading this; it seems the issue was caused by permissions and suexec was part of the issue. Having disabled suexec, all is well again (subject to consequential issues I may find later).
Two files I have in (say) dir1, in /cgi-bin/dashboard-login/ and they use CGI::Session to manage the session.
Both files set a new session like this:
my $session = new CGI::Session(undef, $cgi, {Directory=>"$sessions_dir_location"}) or die CGI::Session->errstr;
This means the second file is actually opening the session created by file1. All good so far.
File 3 is in the same sub-domain but in a different dir (/cgi-bin/dashboard/). It also runs that session string but I get the following error:
Software error:
new(): failed: load(): couldn't retrieve data: retrieve(): couldn't open '/var/www/vhosts/example.com/sessions_storage/cgisess_fc6c62eee135f6cd418defef4516a59c': Permission denied at index line 38.
For help, please send mail to the webmaster (root#localhost), giving this error message and the time and date of the error.
In Filezilla, I see that the file permission is set to "dfr (0640)" for the latest session file but, the previous one has the permissions "adfr (0640)" That adfr file can be opened in filezilla and didn't have any issues when I ran my scripts. Now the session files are being created as "dfr (0640)". IS there a way to set the server (or the CGI::Session), to apply "adfr (0640) permissions?
And, in your experience, is that the likely cause of the problem?
Here you go Håkon Hægland
ls -l /var/www/vhosts/myDomain.com/sessions_storage
-rw-r-----. 1 MyUserName psacln 166 Jan 26 01:22 cgisess_0741489d1010b7ab36f86420e5c58e84
-rw-r-----. 1 apache apache 1769 Jan 26 12:35 cgisess_2d475576f960f6c5407d7a273c02ead1
ls -l /var/www/vhosts/domainName.com/subDomain.myDomain.com/cgi-bin/dashboard-login
-rwxr-xr-x. 1 MyUserName psacln 30628 Jan 26 01:46 login.pl
-rwxr-xr-x. 1 MyUserName psacln 48391 Jan 26 00:49 login-with-pin.pl
ls -l /var/www/vhosts/domainName.com/subDomain.myDomain.com/cgi-bin/dashboard
-rwxr-xr-x. 1 MyUserName psacln 40742 Jan 24 17:47 web_content_manager
For anyone else reading this, it was a permissions issue. It seems to relate to SuExec. Having disabled SuExec, temporarily, until I learn more about directory locations and permissions fully, all is well again.

Remove line in text file if it contains string and then remove the next two lines

I tried Remove a line of text and the next 0 to 5 lines with powershell 2 but that removed everything in my script.
I'm building a PowerShell script to parse an LMtools output.
I have a line that takes out anything that is not in use
$body = (($body -split "`n") |
Where-Object {$_ -notmatch 'Total of 0 licenses in use'}) -join "`n"
I don't need to see packages in use as the following two licenses show exactly what is in use.
I need to remove lines with Users of Package: and the two following lines.
So this:
Users of Package: Autodesk AutoCAD: (Total of 1 license issued; Total of 1 license in use)
"Package: Autodesk AutoCAD" v1.000, vendor: adskflex, expiry: permanent(no expiration date)
UserH ybw-w7-15021 ybw-w7-15021 (v1.000) (licenseserver/27000 490), start Mon 2/25 10:38
Users of Package: AutoCAD - including specialized toolsets: (Total of 1 license issued; Total of 1 license in use)
"Package: AutoCAD - including specialized toolsets" v1.000, vendor: adskflex, expiry: 15-feb-2020
UserA DC18007-W10 DC18007-W10 (v1.000) (licenseserver/27000 114), start Mon 2/25 10:50
Users of Autodesk AutoCAD 2017: (Total of 4 licenses issued; Total of 1 license in use)
"Autodesk AutoCAD 2017" v1.000, vendor: adskflex, expiry: 15-feb-2020
UserA DC18007-W10 DC18007-W10 (v1.0) (licenseserver/27000 214), start Mon 2/25 10:50
Users of Autodesk AutoCAD 2015: (Total of 4 licenses issued; Total of 1 license in use)
"Autodesk AutoCAD 2015" v1.000, vendor: adskflex, expiry: permanent(no expiration date)
UserH DCw7-15021 DCw7-15021 (v1.0) (licenseserver/27000 390), start Mon 2/25 10:38
just becomes this:
Users of Autodesk AutoCAD 2017: (Total of 4 licenses issued; Total of 1 license in use)
"Autodesk AutoCAD 2017" v1.000, vendor: adskflex, expiry: 15-feb-2020
UserA DC18007-W10 DC18007-W10 (v1.0) (licenseserver/27000 214), start Mon 2/25 10:50
Users of Autodesk AutoCAD 2015: (Total of 4 licenses issued; Total of 1 license in use)
"Autodesk AutoCAD 2015" v1.000, vendor: adskflex, expiry: permanent(no expiration date)
UserH DCw7-15021 DCw7-15021 (v1.0) (licenseserver/27000 390), start Mon 2/25 10:38
You could read the input line by line and then skip lines matching "Users of Package:" and the next two lines. However, since your entire input file seems to consist of groups of 3 lines I'd probably use Select-String with a negative lookahead assertion.
$pattern = '^Users of (?!Package:)'
Get-Content 'input.txt' | Select-String $pattern -Context 0,2 | ForEach-Object {
$_.Line
$_.Context.PostContext
} | Set-Content 'output.txt'
The pattern matches the string "Users of " at the beginning of a line (^) when it is not followed by the string "Package:".
Using -Context 0,2 includes the subsequent two input lines with the match.

print text between 2 pattern when find a match inside

for one of my script i need to print text between 2 pattern when a match if found inside, i dont find how to make it simple.
the content of the file is:
===== seble dom0 report =====
IP address: 10.42.0.100
location: slot-3.enclosure-43.eqx
ID: infra-dom0.dom0.seble
Xen-Version: 4.4
CPU: Intel(R) Xeon(R) CPU E5-2660 v3 # 2.60GHz
===== arnica dom0 report =====
IP address: 10.1.42.46
location: slot-3.enclosure-12.eqx
ID: infra-dom0.dom0-3
Xen-Version: 4.1
CPU: AMD Opteron(tm) Processor 6174
===== sithtemd dom0 report =====
IP address: 10.1.42.191
location: slot-13.enclosure-7.vty
ID: infra-dom0.mutu119
Xen-Version: 4.4
CPU: Intel(R) Xeon(R) CPU X5670 # 2.93GHz
if i seach enclosure-7 for exemple i would like it return :
===== sithtemd dom0 report =====
IP address: 10.1.42.191
location: slot-13.enclosure-7.vty
ID: infra-dom0.mutu119
Xen-Version: 4.4
CPU: Intel(R) Xeon(R) CPU X5670 # 2.93GHz
It's a mix between a grep and a sed -n "/===== /,/^$/p" but can't find it...
Thanks in advance for your answers :)
This is the answer:
perl -0777 -lne 'print for grep /enclosure-7/, /^=====.*?^$.*?\n/mgs' file.txt
p will be treated as a regular expression
awk -v p='enclosure-7' -v RS= '$0~p' file.dat
Empty RS means that records are separated by one or more blank lines and nothing else.
With sed:
sed '/^=====/{:a;N;/\n$/!ba;/enclosure-7/!d}' file

Trying to add an after-queue mail filter in Postfix on CentOS, get execvp permission denied

So I followed [the guide][1] on how to set up a simple mail filter with Postfix, so that I can do a find-replace in the body of outgoing emails. I created a script at /tmp/mailfilter.sh, and changed the /etc/postfix/master.cf file as instructed
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
-o content_filter=filter:dummy
filter unix - n n - 10 pipe
flags=Rq user=filter null_sender=
argv=/tmp/mailfilter.sh -f ${sender} -- ${recipient}
I created a user called filter and made it the owner of the script. But when I tried sending an email, I get the following error:
Jun 7 03:01:53 localhost postfix/qmgr[31288]: 134D944A0673: from=<sender#gmail.com>, size=894, nrcpt=1 (queue active)
Jun 7 03:01:53 localhost pipe[31603]: fatal: pipe_command: execvp /tmp/mailfilter.sh: Permission denied
Jun 7 03:01:53 localhost postfix/pipe[31562]: 134D944A0673: to=<receiver#gmail.com>, relay=filter, delay=8974, delays=8974/0/0/0.01, dsn=4.3.0, status=deferred (temporary failure. Command output: pipe: fatal: pipe_command: execvp /tmp/mailfilter.sh: Permission denied )
Specifically what I'm assuming is relevant is
(temporary failure. Command output: pipe: fatal: pipe_command: execvp /tmp/mailfilter.sh: Permission denied )
/tmp/mailfilter.sh has chmod a+x and is owned by filter. I tried removing everything in it so it's just an empty file, and I still get the permission denied error.
I can't figure out what I'm missing. I've set every permission I can find, but Postfix is doing something arcane that I don't understand.
CentOS uses SELinux as a MAC framework, so maybe you need to set properly the type of your executable. You can check in /var/log/audit/audit.log for any security violation. If SELinux is denying you, you can try this command as root:
chcon -t postfix_pipe_exec_t /tmp/mailfilter.sh
That manual is a good reference: http://linux.die.net/man/8/postfix_selinux

Can't apply unified diff patch on Solaris

For example, if I have two files:
file1:
This is file 1
and file2:
This is file 2
and create patch with the following command:
diff -u file1 file2 > files.patch
result is:
--- file1 Fri Aug 13 17:53:28 2010
+++ file2 Fri Aug 13 17:53:38 2010
## -1,1 +1,1 ##
-This is file 1
+This is file 2
Then if I try to apply this patch on Solaris with patch command:
patch -u -i files.patch
it hangs on:
Looks like a unified context diff.
File to patch:
1. Is there a way to use Solaris native patch command with unified diffs?
2. Which diff format is considered most portable if it's not possible to apply unified format?
Update:
I've found answer on the first part of my question. Seems that patch on Solaris hangs if the second file (file2 in this case) exists in the same folder as the first one (file1). For example, the following quite common diff:
--- a/src/file.src Sat Aug 14 23:07:29 2010
+++ b/src/file.src Sat Aug 14 23:07:37 2010
## -1,2 +1,1 ##
-1
-
+2
will not work with quite common patch command:
patch -p1 -u -d a < file.patch
while the following diff (note second file is renamed):
--- a/src/file.src Sat Aug 14 23:07:29 2010
+++ b/src/file_new.src Sat Aug 14 23:07:37 2010
## -1,2 +1,1 ##
-1
-
+2
will work perfectly.
For the second part of my question see accepted answer below.
On Solaris /usr/bin/patch is an old version required to comply with some ancient standards.
A modern version of GNU patch is provided as /usr/bin/gpatch on Solaris 8 and later.
diff -cr old.new new.txt > patch.txt
gpatch -p0 < patch.txt
Works perfectly for me (using gpatch)
Single Unix v2 and v3 both support context diffs but not unified diffs, so for better portability you should use context diffs (-c option to diff and patch).
On older Solaris releases (pre-10, I think), you need to make sure that /usr/xpg4/bin is before /usr/bin in your $PATH, otherwise you may get compatibility versions of some utilities instead of standard ones.