search snippets

Recursive find and replace on OSX/Linux

Tagged search, replace, sed, osx  Languages bash

NOTE: remember to exclude the .git folder…

Search and replace XXX with YYY in all files:

perl -e "s/XXX/YYY/g;" -pi $(find . -type f)

Troubleshooting

If you get this error:

zsh: argument list too long: perl

Your argument list is clearly too long. Try this instead, or use xargs:

find . \
   -type f \
   -exec perl -i -pe's/XXX/YYY/g' {} +

Search and Replace with Sed

Using sed is more complicated, but this should at least work on Linux:

# Find, backup and replace
find . -name "*.rb" -print | xargs sed -i.bak 's/XXX/YYY/g'
# Delete backup files
find . -name '*.bak' -type f -delete

Reference.

Also see: https://snippets.aktagon.com/snippets/861-search-and-replace-file-contents-and-file-names

Big Search Field & Button = Beautiful?

Tagged form, input, search  Languages html
<html>
<head>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css"/>
<style>

.search-form {
  width: 40%;
  min-width: 400px;
  border: 6px solid rgba(0, 0, 0, 0.7);
  margin: 20px auto 0;
}

input.text {
  float: left;
  width: 80%;
  border: 5px solid #fff;
  margin: 0;
  outline: none;
  font-size: 17px;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  -ms-border-radius: 0;
  -o-border-radius: 0;
  border-radius: 0;
  -webkit-appearance: none;
  color: #3c3c3c;
}


input.text, input.button {
  padding: 15px;
  font-size: 17px;
  font-weight: 800;
  display: inline-block;
  -webkit-transition: all 0.3s ease;
  -moz-transition: all 0.3s ease;
  -o-transition: all 0.3s ease;
  transition: all 0.3s ease;
}

input.button {
  float: right;
  width: 20%;
  margin: 0;
  border: 5px solid grey;
  color: #fff;
  background-color: grey;
  -webkit-appearance: none;
  padding-left: 0;
  padding-right: 0;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  -ms-border-radius: 0;
  -o-border-radius: 0;
  border-radius: 0;
}

.clearfix {
  overflow: auto;
}

* {
  font-family: "Helvetica", sans-serif;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

</style>
</head>
<body>
  <div class="search-form clearfix">
    <input name="query" class="text" type="text" placeholder="Find your dog&hellip;">
    <input type="submit" value="Search" class="button">
  </div>
</body>
</html>

Postgres substring search with trigrams

Tagged trigram, postgres, search, substring, unaccent, pgtrgm, pg_trgm  Languages sql

What we have is: * a table "companies" and a column "name" * Postgres and the pgtrgm extension * a company named "Berkshéiße"

Let's enable the trigram extension:

-- $ psql app_schema -U superuser
CREATE EXTENSION pg_trgm;

Now we can search for trigrams, including shèiß

-- $ psql app_schema -U user
SELECT * FROM companies WHERE name ~* 'shèiß';

The query returns nothing, so let's do this instead: * install the unaccent extension * create an "immutable unaccent" function * apply "unaccent" and "lower" to the query * apply "unaccent" and "lower" to the index

-- $ psql app_schema -U superuser
CREATE EXTENSION unaccent;
-- $ psql app_schema -U user
--DROP INDEX companies_name_search_idx;
CREATE OR REPLACE FUNCTION f_unaccent(text)
  RETURNS text AS
$func$
SELECT unaccent('unaccent', $1)
$func$  LANGUAGE sql IMMUTABLE SET search_path = public, pg_temp;
CREATE INDEX companies_name_search_idx ON companies USING gin(f_unaccent(name) gin_trgm_ops);

Finally, the query returns what we're looking for:

-- Plain SQL
SELECT * FROM companies WHERE lower(f_unaccent(name)) LIKE ('%' || lower(f_unaccent('shèiß')) || '%');
-- With pg_trgrm syntax
SELECT * FROM companies WHERE lower(f_unaccent(name) ~* lower(f_unaccent('shéiße'));
-- Look, even this works
SELECT * FROM companies WHERE lower(f_unaccent(name) ~* lower(f_unaccent('shEiSe'));

If Postgres still doesn't use the index we created, it's probably because it's faster to scan the table than using the index.

Notes

* The WHERE-condition must match the index definition:

-- yes
lower(unaccent_text(name) ~* lower(unaccent_text('shéiße'))
-- no
name ~* lower(unaccent_text('shéiße'))
-- no
name ~* unaccent_text('shéiße')

References

* Erwin Brandstetter: Does PostgreSQL support “accent insensitive” collations? * Erwin Brandstetter: PostgreSQL accent + case insensitive search

Search and replace file contents and file names

Tagged bash, find, replace, search, zsh  Languages bash

Search and replace file contents

# Replace Tree with Trees
# NOTE: If you want to backup the files, change -i '' to -i (without empty string)
grep -rl Tree . |xargs sed -i '' -e 's/Tree/Trees/'

Search and replace of file names

find . -name '*observation*' -exec bash -c 'mv $0 ${0/observation/condition}' {} \;

References https://www.commandlinefu.com/commands/matching/search-replace/c2VhcmNoIHJlcGxhY2U=/sort-by-votes