I'm trying to figure out how to extract particular fields from multi line records separated by \n\n.
In this instance, it happens to be output from apt-cache akin to DEBIAN control files. See output of apt-cache show "$package"
Package: caffeine
Priority: optional
Section: misc
Installed-Size: 641
Maintainer: Reuben Thomas <rrt#sc3d.org>
Architecture: all
Version: 2.8.3
Depends: python3:any (>= 3.3.2-2~), python3, gir1.2-gtk-3.0, gir1.2-appindicator3-0.1, python3-xlib, python3-pkg-resources, libnet-dbus-perl
Filename: pool/main/c/caffeine/caffeine_2.8.3_all.deb
Size: 58774
MD5sum: 4438db3f6d1cf43a4f4b49cc7f24cda0
SHA1: e748370ac5ccd7de6fc9466ce0451d2e90d179d4
SHA256: ae303b4e32949cc1e1af80df7217e3406291679e3f18fa8f78a5bbb97504c4f6
Description-en: Prevent the desktop becoming idle in full-screen mode
Caffeine stops the desktop becoming idle when an application
is running full-screen. A desktop indicator ‘caffeine-indicator’
supplies a manual toggle, and the command ‘caffeinate’ can be used
to prevent idleness for the duration of any command.
Description-md5: 7c14f8adc007b10f6ecafed36260bedb
Package: caffeine
Priority: optional
Section: misc
Installed-Size: 655
Maintainer: Reuben Thomas <rrt#sc3d.org>
Architecture: all
Version: 2.6+555~ubuntu14.04.1
Depends: python:any (<< 2.8), python:any (>= 2.7.5-5~), python, gir1.2-gtk-2.0, gir1.2-appindicator3-0.1, x11-utils, python-dbus
Filename: pool/main/c/caffeine/caffeine_2.6+555~ubuntu14.04.1_all.deb
Size: 58604
MD5sum: 1051c3f7d40d344f986bb632d7436849
SHA1: 5e5f622595e8cbba8fb7468b3cffe2914b0ba110
SHA256: 11c5bbf2d28dcda6a7b82872195f740f1f79521b60d3c9acea3037bf0ab3a60e
Description: Prevent the desktop becoming idle
Caffeine allows the user to prevent the desktop becoming idle,
either manually or when certain applications are run. This
prevents screen-blanking, locking, suspending, and so on.
Description-md5: 738866350e5086e77408d7a9c7ffa59b
Package: caffeine
Status: install ok installed
Priority: optional
Section: misc
Installed-Size: 794
Maintainer: Isaiah Heyer <freshapplepy#gmail.com>
Architecture: all
Version: 2.4.1+478~raring1
Depends: dconf-gsettings-backend | gsettings-backend, python (>= 2.6), python-central (>= 0.6.11), python-xlib, python-appindicator, python-xdg, python-notify, python-kaa-metadata
Description: Caffeine
A status bar application able to temporarily prevent the activation
of both the screensaver and the "sleep" powersaving mode.
Description-md5: 1c29acf1ab0f2e6636db29fbde1d14a3
Homepage: https://launchpad.net/caffeine
Python-Version: >= 2.6
My desired output is one line per record in the format apt-get download $pkg=$ver -a=$arch. Basically a list of the installation commands for available packages...
So far what I've got is apt-cache show "$package" | awk '/^Package: / { print $2 } /^Version: / { print $2 } /^Architecture: / { print $2 }' | xargs -n3 | awk '{printf "apt-get download %s=%s -a=%s\n", $1, $3, $2}'
This is the actual output:
apt-get download caffeine=2.8.3 -a=all
apt-get download caffeine=2.6+555~ubuntu14.04.1 -a=all
apt-get download caffeine=2.4.1+478~raring1 -a=all
The is as desired but it appears to be a fluke only because the order of the fields is consistent in this example. It would break if the order of fields was different.
I can do parsing like this using object orientation in Python but I'm having difficulty getting this done in one awk command. The only way I can see doing this correctly would be to split each record into individual tmp files (using split or something along those lines) and then parse each file individually (which is straightforward). Obviously I'd really like to avoid unnecessary I/O as this seems like something that awk is well equipped for. Any awk pro's know how to solve this? I'd even be open to a Perl one-liner or utilizing bash but I'm really interested in learning how to better leverage awk.
$ package=sed
$ apt-cache show "$package" | awk '/^Package: /{p=$2} /^Version: /{v=$2} /^Architecture: /{a=$2} /^$/{print "apt-get download "p"="v" -a="a}'
apt-get download sed=4.2.1-10 -a=amd64
How it works
/^Package: /{p=$2}
Save the package information in variable p.
/^Version: /{v=$2}
Save the version information in variable v.
/^Architecture: /{a=$2}
Save the architecture information in variable a.
/^$/{print "apt-get download "p"="v" -a="a}
When we reach a blank line, print out the information in the desired form.
My version of apt-cache always outputs a blank line after each package. Your sample output is missing the last blank line. If your apt-cache genuinely does not produce that last blank line, then we will need to add a little bit more code to compensate.
As a matter of style, some may prefer printf to print. In which case, replace the above with:
/^$/{printf "apt-get download %s=%s -a=%s\n",v,p,a}'
I find the best way to deal with data that contains name to value pairings is to create an array of those pairs and then just access the values by their names:
$ cat tst.awk
BEGIN { RS=""; FS="\n" }
{
delete n2v
for (i=1;i<=NF;i++) {
if ($i !~ /^ /) {
name = gensub(/:.*/,"","",$i)
value = gensub(/[^:]+:\s+/,"","",$i)
n2v[name] = value
}
}
printf "apt-get download %s=%s -a=%s\n",
n2v["Package"], n2v["Version"], n2v["Architecture"]
}
$ awk -f tst.awk file
apt-get download caffeine=2.8.3 -a=all
apt-get download caffeine=2.6+555~ubuntu14.04.1 -a=all
apt-get download caffeine=2.4.1+478~raring1 -a=all
The above uses a couple of gawk extensions but is easily adapted to any awk if necessary.
Related
The goal is to compare the list of rpms under folder /tmp/list_of_rpms to installed rpm, and if the package is installed with a lower version then print this rpm.
The approach to check if rpm is installed or not can be easily verified with
rpm -qi gssproxy-0.7.0-30.el7_9.x86_64.rpm
package gssproxy-0.7.0-30.el7_9.x86_64.rpm is not installed
but actually this rpm installed with lower version as
rpm -qa | grep gssproxy
gssproxy-0.7.0-29.el7.x86_64
Can we identify also if rpm is installed with lower version?
The approach to take the installed rpm by rpm -qa | grep gssproxy
and then comparing it to the rpm file /tmp/gssproxy-0.7.0-30.el7_9.x86_64.rpm by regex is very complicated.
There's a dedicated tool called rpmdev-vercmp for comparing RPM versions. It's in the yum-utils package. apparently in a package named rpmdevtools.
Untested, but hopefully sufficient to get you started:
for rpm in /tmp/list_of_rpms/*.rpm; do
base=${rpm#/tmp/list_of_rpms/}
pkg=${base%-*-*}
if installed=$(rpm -q "$base"); then
rpmdev-vercmp "$pkg" "$installed" >/dev/null 2>&1
case $? in 12) echo "$installed is less than $pkg";; esac
fi
done
This doesn't do anything for packages which are not installed at all; perhaps you want to add an else clause and add a notification about those, too?
Some background from https://www.golinuxhub.com/2018/06/how-to-compare-rpm-version-bash-script-python-linux-algorithm/ but the actual code in that has problems. Also, https://unix.stackexchange.com/questions/163702/bash-script-to-verify-that-an-rpm-is-at-least-at-a-given-version
I have three files named
file1.txt
file2.txt
file3.txt
I am trying to rename them to
mynewfile-1.txt
mynewfile-2.txt
mynewfile-3.txt
How would I go about this using regular expressions?
Like this :
rename -n 's/^file/mynewfile-/' *.txt
or from comments :
rename -n 's/^file(\d+)/mynewfile-${1}-test/' *.txt
___ ____
^ ^
capturing group |
captured group
Drop -n switch when the output looks good to rename for real.
There are other tools with the same name which may or may not be able to do this, so be careful.
The rename command that is part of the util-linux package, won't.
If you run the following command (GNU)
$ rename
and you see perlexpr, then this seems to be the right tool.
If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :
$ sudo apt install rename
$ sudo update-alternatives --set rename /usr/bin/file-rename
For archlinux:
pacman -S perl-rename
For RedHat-family distros:
yum install prename
The 'prename' package is in the EPEL repository.
For Gentoo:
emerge dev-perl/rename
For *BSD:
pkg install p5-File-Rename
For Mac users:
brew install rename
If you don't have this command with another distro, search your package manager to install it or do it manually
Or you can use perl CPAN:
cpan -i File::Rename
Old standalone version can be found here
man rename
This tool was originally written by Larry Wall, the Perl's dad.
Ubuntu 14.04 LTS
I know traditional approach is using sudo apt-cache search, but this command isn't best method. For example, if i want to search numpy, it will show many irrelevant packages just like following. I need to search one by one, is there better method?
.....
python3-tables-dbg - hierarchical database for Python 3 based on HDF5 (debug extension)
python3-tables-lib - hierarchical database for Python3 based on HDF5 (extension)
reinteract - Worksheet-based graphical Python shell
stimfit - Program for viewing and analyzing electrophysiological data
stimfit-dbg - Debug symbols for stimfit
texlive-lang-italian - TeX Live: Italian
python-spyderlib-doc - python IDE for scientists (Documentation)
python3-spyderlib - python IDE for scientists (Python 3)
spyder-common - python IDE for scientists (common files)
......
apt-cache search searches the package name and description for the given regex pattern, you can make the Regex pattern more robust and search only on the package names by --names-only option:
apt-cache search --names-only '^python3?-numpy'
Also you don't need sudo to run apt-cache.
^python3?-numpy matches package names begin with python3-numpy or python-numpy
If you want to search only on the python3 packages, use ^python3-numpy
To just get the package names:
apt-cache search --names-only '^python3?-numpy' | awk '{print $1}'
Example:
$ apt-cache search --names-only '^python3?-numpy'
python-numpy - Numerical Python adds a fast array facility to the Python language
python-numpy-dbg - Fast array facility to the Python language (debug extension)
python-numpy-doc - NumPy documentation
python3-numpy - Fast array facility to the Python 3 language
python3-numpy-dbg - Fast array facility to the Python 3 language (debug extension)
python-numpydoc - Sphinx extension to support docstrings in Numpy format
$ apt-cache search --names-only '^python3?-numpy' | awk '{print $1}'
python-numpy
python-numpy-dbg
python-numpy-doc
python3-numpy
python3-numpy-dbg
python-numpydoc
opam list -a lists all packages currently available at OPAM, but does not display the version number for packages which are not currently installed, as per the opam list --help output:
(...) the output format displays one package per line, and each line contains the name of the package, the installed version or -- if the package is not installed, (...)
How can I list all packages including their version numbers?
Use opam info <packagename>.
I guess opam list does only prints the versions of already installed packages because of the package dependencies. Listing the latest versions of packages, for example, of not-yet-installed packages is not quite useful.
A refined (and quicker) version of anol's answer is to give the whole list of packages to opam show in one pass (asking opam to output both package and version field), and to process the result with sed, as apparently show outputs each field on its own line:
opam show -f package,version $(opam list -a -s) \
| sed -e '/ *package:/N; s/ *package: \([^\n]*\)\n *version: \([^\n]*\)/\1: \2/'
This is not an ideal solution, but using camlspotter's recommandation, I manually queried each package for its version field, using the following shell loop:
for p in $(opam list -a -s); do echo "$p $(opam show -f version $p)"; done
It works, but it takes ~85 seconds to complete on my machine (querying over 1000 packages currently available).
I'm looking for software that would let me apply changes within lines – not necessarily automaticall – rather than the whole line. I read that wdiff can do this, however there is no Mac OS X version.
If you have Homebrew, you can use:
brew install wdiff
If you want to see the differences in color, try:
brew install colordiff
Then you can do:
wdiff file1.txt file2.txt | colordiff
or
wdiff file1.txt file2.txt | colordiff | less -R
There is (now) a version of wdiff available for Mac OS X. Just install MacPorts and run "sudo port install wdiff".
-Scott
There are probably lots of options for this. The first I came across with a quick Google search is KDiff3.
I use DeltaWalker but use AlternativeTo to see other options